การโหลดภาพไปยัง <img> จาก <input file>


90

ฉันกำลังพยายามโหลดรูปภาพที่ผู้ใช้เลือกผ่านองค์ประกอบ

ฉันเพิ่มตัวจัดการเหตุการณ์ onchange ให้กับองค์ประกอบอินพุตดังนี้:

<input type="file" name="picField" id="picField" size="24" onchange="preview_2(this);" alt=""/>

และฟังก์ชัน Preview_2 คือ:

var outImage ="imagenFondo";
function preview_2(what){
    globalPic = new Image();
    globalPic.onload = function() {
        document.getElementById(outImage).src = globalPic.src;
    }
    globalPic.src=what.value;
}

โดยที่ outImage มีค่า id ของแท็กที่ฉันต้องการให้โหลดรูปภาพใหม่

อย่างไรก็ตามดูเหมือนว่า onload ไม่เคยเกิดขึ้นและไม่โหลดอะไรลงใน html

ฉันควรทำอย่างไรดี?


คำตอบ:


106

ในเบราว์เซอร์ที่รองรับFile APIคุณสามารถใช้ตัวสร้างFileReaderเพื่ออ่านไฟล์เมื่อผู้ใช้เลือกแล้ว

ตัวอย่าง

document.getElementById('picField').onchange = function (evt) {
    var tgt = evt.target || window.event.srcElement,
        files = tgt.files;

    // FileReader support
    if (FileReader && files && files.length) {
        var fr = new FileReader();
        fr.onload = function () {
            document.getElementById(outImage).src = fr.result;
        }
        fr.readAsDataURL(files[0]);
    }

    // Not supported
    else {
        // fallback -- perhaps submit the input to an iframe and temporarily store
        // them on the server until the user's session ends.
    }
}

รองรับเบราว์เซอร์

  • IE 10
  • Safari 6.0.2
  • Chrome 7
  • Firefox 3.6
  • โอเปร่า 12.02.2019

ในกรณีที่ไม่รองรับ File API คุณจะไม่สามารถ (ในเบราว์เซอร์ที่คำนึงถึงความปลอดภัยส่วนใหญ่) รับเส้นทางแบบเต็มของไฟล์จากช่องป้อนไฟล์และไม่สามารถเข้าถึงข้อมูลได้ ทางออกเดียวที่ทำงานได้คือส่งแบบฟอร์มไปยัง iframe ที่ซ่อนอยู่และมีการอัปโหลดไฟล์ไปยังเซิร์ฟเวอร์ล่วงหน้า จากนั้นเมื่อคำขอนั้นเสร็จสมบูรณ์คุณสามารถตั้งค่า src ของรูปภาพเป็นตำแหน่งของไฟล์ที่อัปโหลดได้


ใช่แล้วจึงไม่มีวิธีใดที่ฉันจะอัปโหลดรูปภาพที่เลือกจากผู้ใช้ได้อย่างที่มันคิด ... ?
Valentina

1
ใช่ฉันกำลังมองหาโซลูชัน x-browser ดังนั้นฉันคิดว่าจะลองใช้ตัวเลือกเซิร์ฟเวอร์ ขอบคุณมาก!
Valentina

1
ฉันสงสัยว่าทำไมแปลงเป็น DataURL ไม่ใช่แค่ url วัตถุ?
ShrekOverflow

5
หากคุณต้องการเวอร์ชันซิงโครนัสคุณสามารถใช้: URL.createObjectURL(document.getElementById("fileInput").files[0]);.
КонстантинВан

1
@ КонстантинВанคุณต้องแน่ใจว่าคุณโทรURL.revokeObjectURLเพื่อป้องกันการรั่วไหลของหน่วยความจำ! developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
Dai

53

ดังที่ iEamin กล่าวในคำตอบของเขาตอนนี้ HTML 5 รองรับสิ่งนี้แล้ว ลิงค์ที่เขาให้ไว้http://www.html5rocks.com/en/tutorials/file/dndfiles/นั้นยอดเยี่ยมมาก นี่คือตัวอย่างขั้นต่ำที่อ้างอิงจากตัวอย่างในไซต์นั้น แต่โปรดดูตัวอย่างที่ละเอียดมากขึ้นในไซต์นั้น

เพิ่มตัวonchangeฟังเหตุการณ์ลงใน HTML ของคุณ:

<input type="file" onchange="onFileSelected(event)">

สร้างแท็กรูปภาพด้วย id (ฉันกำลังระบุheight=200เพื่อให้แน่ใจว่าภาพไม่ใหญ่เกินไปบนหน้าจอ):

<img id="myimage" height="200">

นี่คือ JavaScript ของตัวonchangeฟังเหตุการณ์ ใช้Fileวัตถุที่ส่งผ่านเป็นevent.target.files[0]สร้าง a FileReaderเพื่ออ่านเนื้อหาและตั้งค่าตัวฟังเหตุการณ์ใหม่เพื่อกำหนดdata:URL ที่เป็นผลลัพธ์ให้กับimgแท็ก:

function onFileSelected(event) {
  var selectedFile = event.target.files[0];
  var reader = new FileReader();

  var imgtag = document.getElementById("myimage");
  imgtag.title = selectedFile.name;

  reader.onload = function(event) {
    imgtag.src = event.target.result;
  };

  reader.readAsDataURL(selectedFile);
}

ลิงค์เยี่ยม! รหัสที่คุณนำเสนอสำหรับสคริปต์ไม่ได้กำหนดไว้
rashadb

14

$('document').ready(function () {
    $("#imgload").change(function () {
        if (this.files && this.files[0]) {
            var reader = new FileReader();
            reader.onload = function (e) {
                $('#imgshow').attr('src', e.target.result);
            }
            reader.readAsDataURL(this.files[0]);
        }
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="imgload" >
<img src="#" id="imgshow" align="left">

ที่เหมาะกับฉันใน jQuery


วิธีใช้ในกรณีที่ไม่ได้กำหนด "imgload" และ "imgshow" ไว้ล่วงหน้า สมมติว่าฉันมีอินพุตไฟล์ 5 คู่และตัวยึดรูปภาพที่ส่งคืนจากเซิร์ฟเวอร์และรหัสตามลำดับถูกสร้างขึ้นตามดัชนีบางส่วนที่ส่งคืนจากโค้ดของเซิร์ฟเวอร์ด้วย
Ivan

6

ทาง ES2017

// convert file to a base64 url
const readURL = file => {
    return new Promise((res, rej) => {
        const reader = new FileReader();
        reader.onload = e => res(e.target.result);
        reader.onerror = e => rej(e);
        reader.readAsDataURL(file);
    });
};

// for demo
const fileInput = document.createElement('input');
fileInput.type = 'file';
const img = document.createElement('img');
img.attributeStyleMap.set('max-width', '320px');
document.body.appendChild(fileInput);
document.body.appendChild(img);

const preview = async event => {
    const file = event.target.files[0];
    const url = await readURL(file);
    img.src = url;
};

fileInput.addEventListener('change', preview);


1

Andy E ถูกต้องว่าไม่มีวิธีที่ใช้ HTML ในการทำสิ่งนี้ *; แต่ถ้าคุณยินดีที่จะใช้ Flash คุณสามารถทำได้ ต่อไปนี้ทำงานได้อย่างน่าเชื่อถือบนระบบที่ติดตั้ง Flash หากแอปของคุณต้องทำงานบน iPhone แน่นอนว่าคุณจะต้องมีโซลูชันที่ใช้ HTML สำรอง

* ( อัปเดต 4/22/2013:ขณะนี้ HTML รองรับสิ่งนี้แล้วใน HTML5 ดูคำตอบอื่น ๆ )

การอัปโหลด Flash ยังมีข้อดีอื่น ๆ - Flash ช่วยให้คุณสามารถแสดงแถบความคืบหน้าเมื่อการอัปโหลดไฟล์ขนาดใหญ่ดำเนินไป (ฉันค่อนข้างมั่นใจว่า Gmail ทำอย่างไรโดยใช้ Flash อยู่เบื้องหลังแม้ว่าฉันอาจจะคิดผิดก็ตาม)

นี่คือตัวอย่างแอพ Flex 4 ที่อนุญาตให้ผู้ใช้เลือกไฟล์แล้วแสดง:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
               creationComplete="init()">
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <s:Button x="10" y="10" label="Choose file..." click="showFilePicker()" />
    <mx:Image id="myImage" x="9" y="44"/>
    <fx:Script>
        <![CDATA[
            private var fr:FileReference = new FileReference();

            // Called when the app starts.
            private function init():void
            {
                // Set up event handlers.
                fr.addEventListener(Event.SELECT, onSelect);
                fr.addEventListener(Event.COMPLETE, onComplete);
            }

            // Called when the user clicks "Choose file..."
            private function showFilePicker():void
            {
                fr.browse();
            }

            // Called when fr.browse() dispatches Event.SELECT to indicate
            // that the user has picked a file.
            private function onSelect(e:Event):void
            {
                fr.load(); // start reading the file
            }

            // Called when fr.load() dispatches Event.COMPLETE to indicate
            // that the file has finished loading.
            private function onComplete(e:Event):void
            {
                myImage.data = fr.data; // load the file's data into the Image
            }
        ]]>
    </fx:Script>
</s:Application>

เพื่อเป็นการชี้แจงสำหรับผู้ที่กังวลเกี่ยวกับความปลอดภัย: Flash ไม่อนุญาตให้คุณเข้าถึงไฟล์ในเครื่องใด ๆ - อนุญาตให้คุณเข้าถึงไฟล์ในเครื่องที่ผู้ใช้ชี้ไปที่การโต้ตอบเท่านั้น สิ่งนี้คล้ายกับสิ่งที่ HTML ทำ (ช่วยให้คุณสามารถอัปโหลดไฟล์ใด ๆ ที่ระบุอย่างชัดเจนไปยังเซิร์ฟเวอร์) ยกเว้นว่า Flash ยังอนุญาตให้เข้าถึงภายในเครื่องนอกเหนือจากความสามารถในการอัปโหลดไฟล์
Mike Morearty

ฉันอัปโหลดแอปพลิเคชัน Flash ที่ใช้งานได้ที่นี่เพื่อให้คุณสามารถทดลองใช้: morearty.com/preview/FileUploadTest.html
Mike Morearty

1

var outImage ="imagenFondo";
function preview_2(obj)
{
	if (FileReader)
	{
		var reader = new FileReader();
		reader.readAsDataURL(obj.files[0]);
		reader.onload = function (e) {
		var image=new Image();
		image.src=e.target.result;
		image.onload = function () {
			document.getElementById(outImage).src=image.src;
		};
		}
	}
	else
	{
		    // Not supported
	}
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>preview photo</title>
</head>

<body>
<form>
	<input type="file" onChange="preview_2(this);"><br>
	<img id="imagenFondo" style="height: 300px;width: 300px;">
</form>
</body>
</html>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.