Tải hình ảnh vào <img> từ <tệp đầu vào>


87

Tôi đang cố tải một hình ảnh do người dùng chọn thông qua một phần tử.

Tôi đã thêm một trình xử lý sự kiện onchange vào phần tử đầu vào như sau:

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

và hàm preview_2 là:

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

trong đó outImage có giá trị id của thẻ mà tôi muốn tải ảnh mới.

Tuy nhiên, có vẻ như việc quá tải không bao giờ xảy ra và nó không tải bất cứ thứ gì vào html.

Tôi nên làm gì?


Câu trả lời:


102

Trong các trình duyệt hỗ trợ File API , bạn có thể sử dụng hàm tạo FileReader để đọc các tệp khi chúng đã được người dùng chọn.

Thí dụ

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.
    }
}

Hỗ trợ trình duyệt

  • IE 10
  • Safari 6.0.2
  • Chrome 7
  • Firefox 3.6
  • Opera 12.02

Trong trường hợp API tệp không được hỗ trợ, bạn không thể (trong hầu hết các trình duyệt có ý thức bảo mật) lấy đường dẫn đầy đủ của tệp từ hộp nhập tệp, cũng như không thể truy cập dữ liệu. Giải pháp khả thi duy nhất sẽ là gửi biểu mẫu đến một iframe ẩn và tải trước tệp lên máy chủ. Sau đó, khi yêu cầu đó hoàn tất, bạn có thể đặt src của hình ảnh thành vị trí của tệp được tải lên.


đúng, vì vậy không có cách nào tôi có thể tải lên một hình ảnh được chọn từ người dùng chỉ đơn giản như nó nghe ...?
Valentina

1
vâng, tôi đang tìm kiếm các giải pháp trình duyệt x nên tôi nghĩ tôi sẽ thử sử dụng tùy chọn máy chủ. Cảm ơn rât nhiều!
Valentina

1
Tôi tự hỏi tại sao lại chuyển đổi cái này thành DataURL chứ không chỉ là url đối tượng?
ShrekOverflow

4
Nếu bạn muốn phiên bản đồng bộ, bạn có thể sử dụng: URL.createObjectURL(document.getElementById("fileInput").files[0]);.
Константин Ван

1
@ КонстантинВан Bạn phải đảm bảo rằng bạn gọi điện URL.revokeObjectURLđể tránh rò rỉ bộ nhớ! developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
Đài

53

Như iEamin đã nói trong câu trả lời của mình, HTML 5 hiện hỗ trợ điều này. Liên kết mà anh ấy đưa ra, http://www.html5rocks.com/en/tutorials/file/dndfiles/ , rất tuyệt vời. Đây là một mẫu tối thiểu dựa trên các mẫu tại trang web đó, nhưng hãy xem trang web đó để biết các ví dụ kỹ lưỡng hơn.

Thêm trình xử lý onchangesự kiện vào HTML của bạn:

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

Tạo thẻ hình ảnh có id (tôi đang chỉ định height=200để đảm bảo hình ảnh không quá lớn trên màn hình):

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

Đây là JavaScript của trình xử lý onchangesự kiện. Nó nhận Fileđối tượng đã được truyền dưới dạng event.target.files[0], tạo a FileReaderđể đọc nội dung của nó và thiết lập trình xử lý sự kiện mới để gán data:URL kết quả cho imgthẻ:

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);
}

Liên kết tuyệt vời! Tuy nhiên, mã bạn trình bày cho tập lệnh không được xác định.
rashadb

13

$('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">

Điều đó phù hợp với tôi trong jQuery.


Làm thế nào để sử dụng điều này trong trường hợp 'imgload' và 'imgshow' không được xác định trước? Giả sử tôi có 5 cặp đầu vào tệp và trình giữ hình ảnh được trả lại từ máy chủ và id tương ứng của chúng được tạo dựa trên một số chỉ mục cũng được trả lại từ mã của máy chủ.
Ivan,

5

ES2017 Cách

// 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 đúng rằng không có cách nào dựa trên HTML để thực hiện việc này *; nhưng nếu bạn sẵn sàng sử dụng Flash, bạn có thể làm được. Phần sau hoạt động đáng tin cậy trên các hệ thống đã cài đặt Flash. Nếu ứng dụng của bạn cần hoạt động trên iPhone, thì tất nhiên bạn sẽ cần một giải pháp dựa trên HTML dự phòng.

* ( Cập nhật 4/22/2013: HTML hiện hỗ trợ điều này, trong HTML5. Xem các câu trả lời khác.)

Tải lên flash cũng có những ưu điểm khác - Flash cung cấp cho bạn khả năng hiển thị thanh tiến trình khi quá trình tải lên một tệp lớn đang diễn ra. (Tôi khá chắc chắn đó là cách Gmail thực hiện, bằng cách sử dụng Flash đằng sau hậu trường, mặc dù tôi có thể sai về điều đó.)

Đây là một ứng dụng Flex 4 mẫu cho phép người dùng chọn một tệp, sau đó hiển thị nó:

<?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>

Để làm rõ, đối với những người lo lắng về bảo mật: Flash không cho phép bạn truy cập BẤT KỲ tệp cục bộ nào - nó chỉ cho phép bạn truy cập vào một tệp cục bộ đã được người dùng trỏ đến một cách rõ ràng, tương tác. Điều này tương tự như những gì HTML làm (nó cho phép bạn tải bất kỳ tệp nào được chỉ định rõ ràng lên máy chủ), ngoại trừ việc Flash cũng cho phép truy cập cục bộ ngoài khả năng tải tệp lên.
Mike Morearty

Tôi đã tải lên ứng dụng Flash thực thi tại đây để bạn có thể dùng thử: morearty.com/preview/FileUploadTest.html
Mike Morearty 28/09/10

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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.