【问题标题】:Loop over uploaded files and return an array of file signatures循环上传文件并返回一组文件签名
【发布时间】:2020-12-28 19:56:27
【问题描述】:

我想遍历选择上传的文件,获取文件签名并返回文件签名数组。 listOfFileSignatures 数组在 readFirstFourBytes 函数之外是空的。他们是一种使其在全球范围内可访问的方法吗?

var listOfFileSignatures = [];
var totalSize;
var uploadedFiles = document.getElementById("notes").files;
for (file of uploadedFiles) {
    var blob = file;
    var fileReader = new FileReader();
    fileReader.onloadend = function readFirstFourBytes(e) {
        var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
        var fileSignature = "";
        for (var i = 0; i < arr.length; i++) {
            fileSignature += arr[i].toString(16);
        };
        listOfFileSignatures.push(fileSignature);
        console.log(listOfFileSignatures); // Array(3) [ "ffd8ffdb", "ffd8ffe0", "47494638" ]
    };
    fileReader.readAsArrayBuffer(blob);
};
console.log(listOfFileSignatures); // Array [] 

Heres the output

【问题讨论】:

  • 你没有在任何地方声明listOfFileSignatures。在 for 循环之前只需添加 listOfFileSignatures = [];
  • 全局声明,只需将const listOfFileSignatures = [] 放在for (file...) 行之前。
  • @imvain2 我在 for 循环之前有 var listOfFileSignatures = [];
  • @terrymorse 在前循环之前我已经有一个listOfFileSignatures,我已经编辑了代码示例。
  • @simanacci,既然你已经声明了它,这意味着问题只是在你的所有onloadend调用完成之前你的控制台正在运行。这意味着您需要在列表中最后一个文件的 onloadend 中运行使用 listOfFileSignatures 的回调函数。

标签: javascript arrays fileapi


【解决方案1】:

您可以全局声明 listOfFileSignatures,但签名是异步计算的,因此在 for 循环之后列表将直接为空。 FileReader 始终是异步的,因此您无法避免这种情况。解决此问题的一种方法是检查 onloadend (listOfFileSignatures.length == uploadedFiles.length) 中的列表是否已满,然后在那里执行您想要的操作。

更好的方法是使用 Promise,如下所示:

var uploadedFiles = document.getElementById("notes").files;

Promise.all([...uploadedFiles].map(file => new Promise((resolve, reject) => {
    var blob = file;

    var fileReader = new FileReader();
    fileReader.onloadend = function readFirstFourBytes(e) {
        var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
        var fileSignature = "";
        for (var i = 0; i < arr.length; i++) {
            fileSignature += arr[i].toString(16);
        };
        resolve(fileSignature);
    };
    fileReader.readAsArrayBuffer(blob);

}))).then(function(listOfFileSignatures) {
    // this will be called once, when all results are collected.
    console.log(listOfFileSignatures);
});

此外,读取所有字节然后只选择前 4 个字节是低效的。改进版:

Promise.all([...uploadedFiles].map(file => new Promise((resolve, reject) => {
    var blob = file;

    var fileReader = new FileReader();
    fileReader.onloadend = function readFirstFourBytes(e) {
        var arr = new Uint8Array(e.target.result);
        var fileSignature = "";
        for (var i = 0; i < arr.length; i++) {
            fileSignature += arr[i].toString(16);
        };
        resolve(fileSignature);
    };
    fileReader.readAsArrayBuffer(blob.slice(0, 4));

}))).then(function(listOfFileSignatures) {
    // this will be called once, when all results are collected.
    console.log(listOfFileSignatures);
});

【讨论】:

    【解决方案2】:

    fileReader.onload 是异步的,console.log(listOfFileSignatures);在文件被读取之前调用

    一种选择是创建一个返回承诺的外部函数,返回 listOfFileSignatures 数组

    function getListFile() {
        return new Promise((resolve, reject) => { 
            var blob = file;
            var fileReader = new FileReader();
            fileReader.onloadend = function readFirstFourBytes(e) {
                var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
                var fileSignature = "";
                for (var i = 0; i < arr.length; i++) {
                    fileSignature += arr[i].toString(16);
                };
                listOfFileSignatures.push(fileSignature);
                resolve(listOfFileSignatures);
            };
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-12
      • 2019-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多