javascript 使用 readAsDataURL() 进行图像预览
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16430016/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using readAsDataURL() for image preview
提问by whitwhoa
jsFiddle URL: http://jsfiddle.net/Xotic750/AjtLx
jsFiddle 网址:http: //jsfiddle.net/Xotic750/AjtLx
Been working on this all day and I can't see the issue. It's probably due to my narrow understanding of how FileReader objects work but what I'm trying to do is use readAsDataURL() to obtain images a user has selected and preview them on the screen in a table. Everything is working minus...you guessed it...the preview...well sort of. I'm thinking I'm close because the preview will work, BUT it only displays the last image of the set. Say for example if I uploaded 6 images then the first row of 3 images would be broken, the second row the first 2 would be broken, then the final 6th image would display the preview....Any advice greatly appreciated. Also, once this works it might help others trying to do the same thing because I've searched all over for a solution to this issue and I can't seem to dig anything up....
一整天都在研究这个,我看不到这个问题。这可能是由于我对 FileReader 对象如何工作的理解狭隘,但我试图做的是使用 readAsDataURL() 获取用户选择的图像并在表格的屏幕上预览它们。一切正常……你猜对了……预览……差不多。我想我已经接近了,因为预览可以工作,但它只显示集合的最后一张图像。例如,如果我上传了 6 张图像,那么第一行 3 张图像将被破坏,第二行前 2 张将被破坏,然后最后的第 6 张图像将显示预览......任何建议都非常感谢。此外,一旦这奏效,它可能会帮助其他人尝试做同样的事情,因为我已经到处寻找解决这个问题的方法,但我似乎无法挖掘任何东西......
function PreviewImages() {
var inputID = document.getElementById('input_clone');
var totalImages = inputID.files.length;
var imagesPerRow = 3;
var numRows = totalImages / imagesPerRow;
var row = "";
var cell = "";
var element1 = "";
var elementID = "";
for(var i = 0; i < numRows; i++){ //create rows
row = document.getElementById('image_preview_table').insertRow(i);
for(var ii = 0; ii < imagesPerRow; ii++){ //create cells
cell = row.insertCell(ii);
elementID = "img_" + ii;
element1 = document.createElement("img");
element1.name = elementID;
element1.id = elementID
cell.appendChild(element1);
oFReader = new FileReader();
oFReader.onload = function(oFREvent){
var dataURI = oFREvent.target.result;
var image = document.getElementById(elementID);
image.src = dataURI;
};
oFReader.readAsDataURL(document.getElementById("input_clone").files[ii]);
}
}
}
回答by Liang Yan
The problem with your code is: readAsDataURL() is asynchronous, you should wait until it finishes reading before you invoke a second reading or make a new instance by calling new FileReader().
您的代码的问题是: readAsDataURL() 是异步的,您应该等到它完成读取后再调用第二次读取或通过调用 new FileReader() 创建一个新实例。
The answer by Xotic750 works because he creates one FileReader for each image, while you used only one FileReader.
Xotic750 的答案是有效的,因为他为每个图像创建了一个 FileReader,而您只使用了一个 FileReader。
But, using FileReader to preview images is not a good choice, as FileReader.readAsDataURL() converts the whole image to a large string (in the form of "data:image/jpeg;base64,/9j/4SVaRXhpZgAAS......"), and you show the image by placing the whole string of image data into the img.src attribute, if your image is large, you take the risk of running out of memory.
但是,使用 FileReader 预览图像并不是一个好的选择,因为 FileReader.readAsDataURL() 会将整个图像转换为一个大字符串(以“data:image/jpeg;base64,/9j/4SVaRXhpZgAAS ..... ."),并且您通过将整个图像数据字符串放入 img.src 属性来显示图像,如果您的图像很大,则可能会耗尽内存。
img.src is meant to contain the url of the image, not the data of the image, although you can assign a url containing the whole image data via img.src = "data:image/jpeg;......".
img.src 意味着包含图像的 url,而不是图像的数据,尽管您可以通过 img.src = "data:image/jpeg;......" 分配一个包含整个图像数据的 url .
So, you should use window.URL.createObjectURL() to create a url referring to your local image, and assign this url to img.src:
因此,您应该使用 window.URL.createObjectURL() 创建一个引用您本地图像的 url,并将此 url 分配给 img.src:
...
img.src = window.URL.createObjectURL(fileInput.files[i]);
...
回答by Xotic750
Here is a solution, quite a bit of adjustment was made to your original to get it to work, as you will probably notice.
这是一个解决方案,您可能会注意到,对您的原始文件进行了大量调整以使其正常工作。
CSS
CSS
div.rounded {
width: 100%;
border-style: solid;
border-width: 1px;
border-radius: 5px;
}
label {
display: block;
}
input {
display: block;
}
#previewTable {
width: 100%;
}
HTML
HTML
<div id="imagesDiv" class="rounded">
<label for="chooseFiles">Add Images</label>
<input type="file" id="chooseFiles" multiple="multiple" />
<table id="previewTable">
<thead id="columns"></thead>
<tbody id="previews"></tbody>
</table>
</div>
Javascript
Javascript
(function (global) {
var imagesPerRow = 3,
chooseFiles,
columns,
previews;
function PreviewImages() {
var row;
Array.prototype.forEach.call(chooseFiles.files, function (file, index) {
var cindex = index % imagesPerRow,
oFReader = new FileReader(),
cell,
image;
if (cindex === 0) {
row = previews.insertRow(Math.ceil(index / imagesPerRow));
}
image = document.createElement("img");
image.id = "img_" + index;
image.style.width = "100%";
image.style.height = "auto";
cell = row.insertCell(cindex);
cell.appendChild(image);
oFReader.addEventListener("load", function assignImageSrc(evt) {
image.src = evt.target.result;
this.removeEventListener("load", assignImageSrc);
}, false);
oFReader.readAsDataURL(file);
});
}
global.addEventListener("load", function windowLoadHandler() {
global.removeEventListener("load", windowLoadHandler);
chooseFiles = document.getElementById("chooseFiles");
columns = document.getElementById("columns");
previews = document.getElementById("previews");
var row = columns.insertRow(-1),
header,
i;
for (i = 0; i < imagesPerRow; i += 1) {
header = row.insertCell(-1);
header.style.width = (100 / imagesPerRow) + "%";
}
chooseFiles.addEventListener("change", PreviewImages, false);
}, false);
}(window));
On jsfiddle