以编程方式更改输入类型文件的值?
Programmatically changing value of input type file?
我正在尝试生成一些代码,我可以在整个站点中重复使用这些代码,本质上,这些代码是经过一些验证的照片 picker/chooser。这是我的代码:
class PhotoPicker
{
constructor(element)
{
this.element = element;
//Creating needed HTML Markup
this.createMarkUp();
//FileList of valid data.
this.validFiles = new DataTransfer();
//Initialise Picker.
this.input.onchange = () => {
this.updateOutput();
this.output.files = this.validFiles.files;
}
}
updateOutput()
{
const files = Array.from(this.input.files);
files.forEach((file) => {
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
photo = this.createPhotoThumb({
url : reader.result,
name: file.name,
size: file.size
});
if (this.validatePhoto(file)) {
this.validFiles.items.add(file);
};
};
});
}
createMarkUp()
{
//Creating needed HTML Markup
}
createPhotoThumb(data = {})
{
//Creating a photo thumbnail for preview
}
validatePhoto(photo)
{
//Validating the photo
}
}
发生的事情是,当我第一次选择一些图像时,会显示缩略图,并且有效文件列表 this.validFiles.files
会更新,但是 NOT 我计划发送到服务器的最终列表 this.output.files
, 然而 ,在第二次尝试时,它成功了!最终列表更新为第一个选择的文件, NOT 第二个,依此类推。每次选择都更新前一个文件一个被添加到最终列表,但不是上次选择的文件。
我认为问题在于您期望
reader.onload = () => {
photo = this.createPhotoThumb({
url : reader.result,
name: file.name,
size: file.size
});
if (this.validatePhoto(file)) {
this.validFiles.items.add(file);
};
};
get 在您将有效文件分配给 this.output.files
之前执行。
但是 reader.onload
是异步执行的,因此您将有效文件分配给 this.output.files
会在将有效文件添加到有效文件数组之前执行。
您必须实现一些逻辑来等待读者的 onload
处理程序完成。
这可能是一个解决方案:
class PhotoPicker
{
constructor(element)
{
this.element = element;
// Creating needed HTML Markup
this.createMarkUp();
// FileList of valid data.
this.validFiles = new DataTransfer();
// Initialise Picker.
this.input.onchange = () => {
this.updateOutput()
.then(() => {
this.output.files = this.validFiles.files;
});
}
}
updateOutput()
{
const files = Array.from(this.input.files);
const fileLoaderPromises = [];
files.forEach((file) => {
const promise = new Promise((resolve) => {
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
photo = this.createPhotoThumb({
url : reader.result,
name: file.name,
size: file.size
});
if (this.validatePhoto(file)) {
this.validFiles.items.add(file);
};
// Mark the file loader as "done"
resolve();
};
})
// Add the promise to the list of file loader promises
fileLoaderPromises.push(promise);
});
// Return a promise which resolves as soon as all file loader promises are done
return Promise.all(fileLoaderPromises);
}
// ...
}
我正在尝试生成一些代码,我可以在整个站点中重复使用这些代码,本质上,这些代码是经过一些验证的照片 picker/chooser。这是我的代码:
class PhotoPicker
{
constructor(element)
{
this.element = element;
//Creating needed HTML Markup
this.createMarkUp();
//FileList of valid data.
this.validFiles = new DataTransfer();
//Initialise Picker.
this.input.onchange = () => {
this.updateOutput();
this.output.files = this.validFiles.files;
}
}
updateOutput()
{
const files = Array.from(this.input.files);
files.forEach((file) => {
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
photo = this.createPhotoThumb({
url : reader.result,
name: file.name,
size: file.size
});
if (this.validatePhoto(file)) {
this.validFiles.items.add(file);
};
};
});
}
createMarkUp()
{
//Creating needed HTML Markup
}
createPhotoThumb(data = {})
{
//Creating a photo thumbnail for preview
}
validatePhoto(photo)
{
//Validating the photo
}
}
发生的事情是,当我第一次选择一些图像时,会显示缩略图,并且有效文件列表 this.validFiles.files
会更新,但是 NOT 我计划发送到服务器的最终列表 this.output.files
, 然而 ,在第二次尝试时,它成功了!最终列表更新为第一个选择的文件, NOT 第二个,依此类推。每次选择都更新前一个文件一个被添加到最终列表,但不是上次选择的文件。
我认为问题在于您期望
reader.onload = () => {
photo = this.createPhotoThumb({
url : reader.result,
name: file.name,
size: file.size
});
if (this.validatePhoto(file)) {
this.validFiles.items.add(file);
};
};
get 在您将有效文件分配给 this.output.files
之前执行。
但是 reader.onload
是异步执行的,因此您将有效文件分配给 this.output.files
会在将有效文件添加到有效文件数组之前执行。
您必须实现一些逻辑来等待读者的 onload
处理程序完成。
这可能是一个解决方案:
class PhotoPicker
{
constructor(element)
{
this.element = element;
// Creating needed HTML Markup
this.createMarkUp();
// FileList of valid data.
this.validFiles = new DataTransfer();
// Initialise Picker.
this.input.onchange = () => {
this.updateOutput()
.then(() => {
this.output.files = this.validFiles.files;
});
}
}
updateOutput()
{
const files = Array.from(this.input.files);
const fileLoaderPromises = [];
files.forEach((file) => {
const promise = new Promise((resolve) => {
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
photo = this.createPhotoThumb({
url : reader.result,
name: file.name,
size: file.size
});
if (this.validatePhoto(file)) {
this.validFiles.items.add(file);
};
// Mark the file loader as "done"
resolve();
};
})
// Add the promise to the list of file loader promises
fileLoaderPromises.push(promise);
});
// Return a promise which resolves as soon as all file loader promises are done
return Promise.all(fileLoaderPromises);
}
// ...
}