FileReader 在循环中加载并赋值?
FileReader onload and assign value in loop?
我在获取文件 reader 内容分配时遇到困难。无论如何要等待文件 reader 完成加载并在将文件内容推送到数组之前分配文件内容?
我有一个输入文件类型按钮列表如下:
@for (int i = 0; i < @Model.LetterList.Count(); i++)
{
<tr>
<td>
<input type="file" id="LetterAttachment" name="LetterAttachment" accept="application/pdf">
</td>
</tr>
}
当我点击提交时,我想循环将文件内容值分配到我的表单列表中,下面是我的 javascript 代码:
var attach=""; // empty variable for assign file content
function ApproverAction(action) {
var formList = [];
$("input[name='LetterAttachment']").each(function () {
if (this.files && this.files[0]) {
// I perform file reader here to assign the file content into attach....
var FR = new FileReader();
FR.onload = function (e) {
attach = e.target.result;
}
FR.readAsDataURL(this.files[0]);
var form = {
ID: newGuid(),
FileContents: attach, <<< ---- However it showing empty
DocumentName: this.files[0].name,
DocumentSize: this.files[0].size,
DocumentContentType: 'application/pdf',
SourceType: 'OnlineAssessment',
CreatedDate: '@DateTime.Now'
}
formList.push(form);
}
});
console.log(formList);
}
但是我无法完全正确地得到输出结果:
非常感谢任何帮助和提示!谢谢!
这是因为您在 FR.onload
中提供的函数是异步执行的。因此,它之后的代码将在调用函数之前执行,因此 JSON 中的 FileContents
的值为空。
您可以做的是在函数内完成所有您想做的事情,或者使用其他函数,例如 readAsText
。
...
var FR = new FileReader();
FR.readAsDataURL(this.files[0]);
var form = {
ID: newGuid(),
FileContents: FR.readAsText(this.files[0),
DocumentName: this.files[0].name,
DocumentSize: this.files[0].size,
DocumentContentType: 'application/pdf',
SourceType: 'OnlineAssessment',
CreatedDate: '@DateTime.Now'
}
...
参考这个例子 onLoad and readAsText。
对在 onload 函数中解析的每个文件使用一个承诺,并将这些承诺推送到一个数组中
然后在所有承诺都已解决后使用 Promise.all()
发送数据。请注意,错误处理将需要根据您想要的流程进行改进
function ApproverAction(action) {
var filePromises = [];
$("input[name='LetterAttachment']").each(function() {
if (this.files && this.files[0]) {
// reference to this to use inside onload function
var _input = this;
var promise = new Promise(function(resolve, reject) {
var FR = new FileReader();
FR.onload = function(e) {
var form = {
ID: newGuid(),
FileContents: e.target.result;,
DocumentName: _input.files[0].name,
DocumentSize: _input.files[0].size,
DocumentContentType: 'application/pdf',
SourceType: 'OnlineAssessment',
CreatedDate: '@DateTime.Now'
}
// resolve promise with object
resolve(form);
}
FR.readAsDataURL(this.files[0]);
if(FB.error){
// needs more robust error handling, for now just reject promise
reject(FB.error)
}
// push promise to array
filePromises.push(promise)
}
});
}
});
// return a new promise with all the data
return Promise.all(filePromises)
}
使用函数返回的 promise
ApproverAction(action).then(function(formList){
// do something with the data array
console.log(formList);
}).catch(function(err){
console.error("Ooops something went wrong')
});
我在获取文件 reader 内容分配时遇到困难。无论如何要等待文件 reader 完成加载并在将文件内容推送到数组之前分配文件内容?
我有一个输入文件类型按钮列表如下:
@for (int i = 0; i < @Model.LetterList.Count(); i++)
{
<tr>
<td>
<input type="file" id="LetterAttachment" name="LetterAttachment" accept="application/pdf">
</td>
</tr>
}
当我点击提交时,我想循环将文件内容值分配到我的表单列表中,下面是我的 javascript 代码:
var attach=""; // empty variable for assign file content
function ApproverAction(action) {
var formList = [];
$("input[name='LetterAttachment']").each(function () {
if (this.files && this.files[0]) {
// I perform file reader here to assign the file content into attach....
var FR = new FileReader();
FR.onload = function (e) {
attach = e.target.result;
}
FR.readAsDataURL(this.files[0]);
var form = {
ID: newGuid(),
FileContents: attach, <<< ---- However it showing empty
DocumentName: this.files[0].name,
DocumentSize: this.files[0].size,
DocumentContentType: 'application/pdf',
SourceType: 'OnlineAssessment',
CreatedDate: '@DateTime.Now'
}
formList.push(form);
}
});
console.log(formList);
}
但是我无法完全正确地得到输出结果:
非常感谢任何帮助和提示!谢谢!
这是因为您在 FR.onload
中提供的函数是异步执行的。因此,它之后的代码将在调用函数之前执行,因此 JSON 中的 FileContents
的值为空。
您可以做的是在函数内完成所有您想做的事情,或者使用其他函数,例如 readAsText
。
...
var FR = new FileReader();
FR.readAsDataURL(this.files[0]);
var form = {
ID: newGuid(),
FileContents: FR.readAsText(this.files[0),
DocumentName: this.files[0].name,
DocumentSize: this.files[0].size,
DocumentContentType: 'application/pdf',
SourceType: 'OnlineAssessment',
CreatedDate: '@DateTime.Now'
}
...
参考这个例子 onLoad and readAsText。
对在 onload 函数中解析的每个文件使用一个承诺,并将这些承诺推送到一个数组中
然后在所有承诺都已解决后使用 Promise.all()
发送数据。请注意,错误处理将需要根据您想要的流程进行改进
function ApproverAction(action) {
var filePromises = [];
$("input[name='LetterAttachment']").each(function() {
if (this.files && this.files[0]) {
// reference to this to use inside onload function
var _input = this;
var promise = new Promise(function(resolve, reject) {
var FR = new FileReader();
FR.onload = function(e) {
var form = {
ID: newGuid(),
FileContents: e.target.result;,
DocumentName: _input.files[0].name,
DocumentSize: _input.files[0].size,
DocumentContentType: 'application/pdf',
SourceType: 'OnlineAssessment',
CreatedDate: '@DateTime.Now'
}
// resolve promise with object
resolve(form);
}
FR.readAsDataURL(this.files[0]);
if(FB.error){
// needs more robust error handling, for now just reject promise
reject(FB.error)
}
// push promise to array
filePromises.push(promise)
}
});
}
});
// return a new promise with all the data
return Promise.all(filePromises)
}
使用函数返回的 promise
ApproverAction(action).then(function(formList){
// do something with the data array
console.log(formList);
}).catch(function(err){
console.error("Ooops something went wrong')
});