我想在文件夹中加载图像,并希望在我的 js 中获取 base64 中的所有图像以供将来使用
I want to load images withen the folder and want to get all images in base64 in my js for future use
我面临的问题是,由于某种 Filereader 库函数 onloadend,我总是得到图像数组中的最后一张图像。
我怎样才能为我的文件夹中的所有图像获取 base64。
<input id="file-input" multiple webkitdirectory type="file" />
var input = document.getElementById('file-input');
var file_names = "";
var entries_length = 0;
var entries_count = 0;
var image = new Array();
var obj = {};
var j = 0;
input.onchange = function(e) {
var files = e.target.files; // FileList
entries_length = files.length;
console.log(files);
for (var i = 0, f; f = files[i]; ++i){
console.log("i:"+i);
entries_count = entries_count + 1;
//console.debug(files[i].webkitRelativePath);
if(files[i].type=="image/jpeg")
{
var string = files[i].webkitRelativePath;
var name = string.split("/")[3]; //this is because my image in 3rd dir in the folder
var reader = new FileReader();
reader.onloadend = function() {
obj.name = string.split("/")[3];
obj.image = reader.result;
image[j] = obj;
j = j+1;
}
reader.readAsDataURL(files[i]);
}
}
console.log(image);
}
问题是由文件的异步加载引起的。您遍历数组并每次为 reader 设置 onloadend
处理程序,然后通过调用 readAsDataURL
.
开始加载
一个问题是,当您加载第一个图像时,for
循环可能已经完成,并且 i
已经位于数组的最后一个索引处。
此时,从 files[i].webkitRelativePath
获取路径将为您提供最后一个文件名,而不是您期望的文件名。
检查 example for readAsDataURL on MDN 以查看一个可能的解决方案 - 每个加载都在一个单独的函数中执行,该函数保留其范围,以及 file.name
。不要被他们使用的结构推迟:[].forEach.call(files, readAndPreview)
。这是一种映射文件的方法,文件是 FileList 而不是常规数组(因此列表没有自己的 forEach 方法)。
因此,将加载逻辑包装在一个将文件对象作为参数的函数中应该就足够了:
var images = [];
function loadFile(f) {
var reader = new FileReader();
reader.onloadend = function () {
images.push({
name : f.name, // use whatever naming magic you prefer here
image : reader.result
});
};
reader.readAsDataURL(f);
}
for (var i=0; i<files.length; i++) {
loadFile(files[i]);
}
函数的每次调用 'remembers' 调用它的文件对象,并防止文件名弄乱。如果您有兴趣,read up on closures.
这也有很好的隔离你的 reader 对象的效果,因为我有一个潜在的怀疑,虽然你创建了一个新的 'local' reader 每次迭代,javascript 范围规则很奇怪 readers 也可能相互干扰(如果一个 reader 正在加载会发生什么,但是在相同的范围内你创建一个新的 reader 具有相同的变量名?不确定)。
现在,你不知道加载所有图像需要多长时间,所以如果你想在那之后立即采取行动,你必须在每次 onloadend
时执行检查被调用。这就是异步行为的本质。
顺便说一句,我应该注意到手动跟踪 images
的最后一个索引是没有意义的,即 j
。你应该只使用 images.push({ name: "bla", image: "base64..." })
。手动保留索引会带来错误的可能性。
我面临的问题是,由于某种 Filereader 库函数 onloadend,我总是得到图像数组中的最后一张图像。 我怎样才能为我的文件夹中的所有图像获取 base64。
<input id="file-input" multiple webkitdirectory type="file" />
var input = document.getElementById('file-input');
var file_names = "";
var entries_length = 0;
var entries_count = 0;
var image = new Array();
var obj = {};
var j = 0;
input.onchange = function(e) {
var files = e.target.files; // FileList
entries_length = files.length;
console.log(files);
for (var i = 0, f; f = files[i]; ++i){
console.log("i:"+i);
entries_count = entries_count + 1;
//console.debug(files[i].webkitRelativePath);
if(files[i].type=="image/jpeg")
{
var string = files[i].webkitRelativePath;
var name = string.split("/")[3]; //this is because my image in 3rd dir in the folder
var reader = new FileReader();
reader.onloadend = function() {
obj.name = string.split("/")[3];
obj.image = reader.result;
image[j] = obj;
j = j+1;
}
reader.readAsDataURL(files[i]);
}
}
console.log(image);
}
问题是由文件的异步加载引起的。您遍历数组并每次为 reader 设置 onloadend
处理程序,然后通过调用 readAsDataURL
.
一个问题是,当您加载第一个图像时,for
循环可能已经完成,并且 i
已经位于数组的最后一个索引处。
此时,从 files[i].webkitRelativePath
获取路径将为您提供最后一个文件名,而不是您期望的文件名。
检查 example for readAsDataURL on MDN 以查看一个可能的解决方案 - 每个加载都在一个单独的函数中执行,该函数保留其范围,以及 file.name
。不要被他们使用的结构推迟:[].forEach.call(files, readAndPreview)
。这是一种映射文件的方法,文件是 FileList 而不是常规数组(因此列表没有自己的 forEach 方法)。
因此,将加载逻辑包装在一个将文件对象作为参数的函数中应该就足够了:
var images = [];
function loadFile(f) {
var reader = new FileReader();
reader.onloadend = function () {
images.push({
name : f.name, // use whatever naming magic you prefer here
image : reader.result
});
};
reader.readAsDataURL(f);
}
for (var i=0; i<files.length; i++) {
loadFile(files[i]);
}
函数的每次调用 'remembers' 调用它的文件对象,并防止文件名弄乱。如果您有兴趣,read up on closures.
这也有很好的隔离你的 reader 对象的效果,因为我有一个潜在的怀疑,虽然你创建了一个新的 'local' reader 每次迭代,javascript 范围规则很奇怪 readers 也可能相互干扰(如果一个 reader 正在加载会发生什么,但是在相同的范围内你创建一个新的 reader 具有相同的变量名?不确定)。
现在,你不知道加载所有图像需要多长时间,所以如果你想在那之后立即采取行动,你必须在每次 onloadend
时执行检查被调用。这就是异步行为的本质。
顺便说一句,我应该注意到手动跟踪 images
的最后一个索引是没有意义的,即 j
。你应该只使用 images.push({ name: "bla", image: "base64..." })
。手动保留索引会带来错误的可能性。