Axios:多文件上传的上传进度

4

按照https://github.com/mzabriskie/axios/blob/master/examples/upload/index.html中的示例,我已经设置了带进度条的文件上传。

然而,由于我使用了<input type="file" multiple>,所以上传需要通过以下循环完成:

for (var i=0; i<files.length; i++)
{
    var config = {
        onUploadProgress: function(progressEvent) {
            var what = Math.round( (progressEvent.loaded * 100) / progressEvent.total );
        }
    };
    axios.post(url, data, config)
        .then(function (response) {
    });                            
}

问题是:如何将上传进度(请参见var what)分配给相应的文件?
我尝试过的所有方法都没有成功:
  • The callback function onUploadProgress apparently doesn't take any second argument: https://github.com/mzabriskie/axios#request-config

  • The injected progressEvent object doesn't contain any information about the uploaded file. Example:

    progress { target: XMLHttpRequestUpload, isTrusted: true, lengthComputable: true, loaded: 181914, total: 181914, currentTarget: XMLHttpRequestUpload, eventPhase: 2, bubbles: false, cancelable: false, defaultPrevented: false, composed: false }
    
  • The looping variable i is accessible in principle - however, it's always at the last position (since the loop has finished when onUploadProgress gets called during the upload)

  • I couldn't figure out a way to access axios' data from inside onUploadProgress

  • this refers to:

    XMLHttpRequestUpload { onloadstart: null, onprogress: null, onabort: null, onerror: null, onload: null, ontimeout: null, onloadend: null }
    

还有其他想法吗?


我在这里漏了什么吗?您正在for循环内部一次上传一个文件。这意味着在每个progressEvent中,您已经在引用相应的文件。您可以添加一个进度事件的监听器,并输出其“总”值吗?我认为您已经在查看相应的文件了。另外注意一下,将config从for循环中提取出来,您不需要为每个文件重新定义它。 - Samuel Bergström
是的,谢谢,我已经想到答案可能是没有答案了;-) 我只能在几天后尝试一下 - 到时候我会报告... - Thomas Landauer
我也在想如何实现这个。使用jQuery时,我一直在使用“xhrFields”参数,但我不确定Axios是否有类似的东西。 - dvyio
2个回答

10

您可以创建一个返回带有某个Id参数的另一个装饰函数的函数。

例如:

const myUploadProgress = (myFileId) => (progress) => {
  let percentage = Math.floor((progress.loaded * 100) / progress.total)
  console.log(myFileId)
  console.log(percentage)
}

for (var i=0; i<files.length; i++) {
  var config = {
    onUploadProgress: myUploadProgress(files[i].id)
  };

  axios.post(url, data, config).then(function (response) {});                            
}

如果您没有ES6,您可以这样做:

function myUploadProgress(myFileId) {
  return function(progress) {
    ...
  }
}

(我在我的项目中使用类似的代码,它运行得很好)


0
这是一个变量作用域问题。在JavaScript中,var声明的变量是在函数作用域内的。根据目标浏览器支持的ES版本不同,有很多潜在的解决方案。我将使用相同的函数进行演示:
setTimeout(function(){ console.log(i); }, i * 100);

使用 var 这样会打印出 '5' 五次。我们想要它打印出0 1 2 3 4

如果你有 Array#forEach,你可以使用它,因为闭包会创建一个新的函数作用域。

[0, 1, 2, 3, 4].forEach(function(i) { 
    setTimeout(function(){ console.log(i); }, i * 100);
});

如果您可以访问letletconst将使用块级作用域(即变量的作用域限定在最近的一组{ ... }中)。

for (let i = 0; i < 5; i++) {
    setTimeout(function(){ console.log(i); }), i * 100);
}

如果你没有上述任何一种方式的访问权限,你可以使用IIFE。它看起来非常丑陋,但确实能完成工作。

for (var i = 0; i < 5; i++){ 
    (function() {
        var newI = i;
        setTimeout(function(){ console.log(newI); }, i * 100); 
    })();
} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接