过去6个小时我正在研究这个问题,我无法弄清楚这一点。
我正在尝试创建一个网站,我在其中选择图像文件夹,然后在我的文档中显示它们。我得到第一个要显示的图像,然后在我的控制台中出现以下错误。
未捕获的DOMException:无法执行' readAsDataURL' on' FileReader':对象已经忙于阅读Blob。(...)
我认为问题是由于我的for循环引起的,因为filereader是异步的。但是我需要循环遍历整个数组,所以我做错了什么?
我将文件("将检查以确保我以后只获得图像")加载到一个数组中,然后我一次读取一个文件。 在将代码分解为函数之前,我在一个函数中完成了所有操作,并且它可以工作!我包含了HTML +原始和当前的JS代码。 感谢您花时间看这个。
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Tiled Image Viewer</title>
<script src="js/tiv.js"></script>
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="main-wrap">
<form name="uploadForm">
<input id="images" type="file" webkitdirectory mozdirectory directory name="myFiles"
onchange="readAndShowFiles();" multiple/>
<span id="list"></span>
</form>
</div>
</body>
</html>
Javascript原文:
function readAndShowFiles() {
var files = document.getElementById("images").files;
for (var i = 0; i < files.length; i++) {
var file = files[i];
// Have to check that this is an image though
// using the file.name TODO
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(file) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(file);
// Read in the image file as a data URL.
reader.readAsDataURL(file);
}
}
Javascript Current:
function readAndShowFiles() {
console.log("Checkpoint2"); //test
var tiv = new tivAPI();
var array = tiv.getLoadedImages();
tiv.showLoadedImages(array);
}
function tivAPI(){
var imagesarray = new Array();
return{
loadImages: function(){
console.log("Loading Files"); //test
var files = document.getElementById("images").files;
for (var i = 0; i < files.length; i++) {
var file = files[i];
// Have to check that this is an image though
// using the file.name TODO
}
console.log(files.length); //test
return files;
},
getLoadedImages: function(){
imagesarray = this.loadImages();
console.log("Returning Files"); //test
console.log(imagesarray.length);
return imagesarray;
},
showLoadedImages: function(elem){
console.log("Showing Files"); //test
var files = elem;
var reader = new FileReader();
// Closure to capture the file information.
for (var i = 0; i < files.length; i++) {
var file = files[i];
reader.onload = (function(file) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(file);
// Read in the image file as a data URL.
reader.readAsDataURL(file);
}
}
};
}
答案 0 :(得分:6)
你的代码使用同一个阅读器的原因是因为你使用相同的阅读器变量。
所谓的javascript是所有变量都被移到顶部所以你的解析代码看起来像这样
function readAndShowFiles() {
var files = document.getElementById("images").files;
var reader;
var file;
var i;
for (i = 0; i < files.length; i++) {
file = files[i];
reader = new FileReader();
reader.onload = (function(file) {
return function(e) {
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'
].join('');
document.getElementById('list').insertBefore(span, null);
};
})(file);
reader.readAsDataURL(file);
}
}
只需移动annonymes函数中的所有逻辑就可以避免它变得非常简单
function readAndShowFiles() {
var files = document.getElementById("images").files;
for (var i = 0; i < files.length; i++) {
// Closure to capture the file information.
(function(file) {
var reader = new FileReader();
reader.onload = function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'
].join('');
document.getElementById('list').insertBefore(span, null);
};
// Read in the image file as a data URL.
reader.readAsDataURL(file);
})(files[i]);
}
}
现在您正在为每个文件使用uniq阅读器。另请注意,如果您刚刚执行此操作可能会更简单
array.from(files).forEach(function(file) {
// code
})
或者只是使用了let
变量(这样每次都会使用不同的FileReader
)
function readAndShowFiles() {
var files = document.getElementById("images").files;
for (var i = 0; i < files.length; i++) {
let file = files[i];
let reader = new FileReader();
reader.onload = function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'
].join('');
document.getElementById('list').insertBefore(span, null);
};
// Read in the image file as a data URL.
reader.readAsDataURL(file);
}
}
使用es6可以更容易地编写for循环,从而减少2个变量
function readAndShowFiles() {
var files = document.getElementById("images").files;
for (let file of files) {
let reader = new FileReader();
reader.onload = function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'
].join('');
document.getElementById('list').insertBefore(span, null);
};
// Read in the image file as a data URL.
reader.readAsDataURL(file);
}
}
但是如果你想要它非常容易,为什么不一起跳过FileReader
所有功能并避免所有功能&amp;使用createObjectURL与URL.createObjectURL
进行回调,您可以将文件保存到/从base64编译文件
function showFiles() {
var files = document.getElementById("images").files;
for (let file of files) {
let img = new Image;
img.src = URL.createObjectURL(file);
img.title = file.name;
document.getElementById('list').appendChild(img);
}
}
答案 1 :(得分:2)
问题发生了,因为我试图为每个图像使用相同的阅读器。
将var reader = new FileReader();
移动到循环(ShowLoadedImages函数)中,解决了问题并显示了它应该的所有图像。