首页 > 解决方案 > 使用 Promise.all 为 AWS Node.js 上传创建进度条

问题描述

我一直在玩下面的代码,试图将我当前的 AWS 上传器减少到几行代码。这段代码效果很好,但我真的需要一个进度指示器来监控上传进度,因为对于较大的文件或文件夹上传,用户不知道需要多长时间。

我是新的承诺等待等我当前的代码使用回调。

我在这里看到了这段代码。 ES6 Promise.all 进度

是否可以为每个成功上传的文件获取回调?这样我就可以获取所有要上传的文件的总长度,并基于该增量输出一个进度。

这是我当前的代码。

let AWS = require("aws-sdk");

const fs = require('fs');

const path = require('path');

const s3 = new AWS.S3();

const params = [];

fs.readdirSync('/Users/dave/Desktop/uploadit').forEach(file => {

    const {
        ext,
        name,
        dir
    } = path.parse(file);

    let fl = name.replace(/[^a-z0-9/]/gi, '_').toLowerCase();

    params.push({ 
        Bucket: 's3b-south-amercia', 
        Key: fl + ext, 
        Body: fs.readFileSync('/Users/dave/Desktop/uploadit/' + file)
    });

});

var total_files = params.length;

// Start function
const start = async function(a, b) {
    
    console.time('test');

    const responses = await Promise.all(
        params.map(param => s3.upload(param).promise())
    );

    console.timeEnd('test');

}

// Call start
start();

// time aws s3 cp /Users/dave/Desktop/uploadit s3://s3b-south-amercia/ --recursive
// AWS CLI 26.295 / 24.684s
// AWS NODE 27.859s / 20.483

我已经针对 AWS cli line cp 命令测试了代码,它们都有相似的上传时间。

任何帮助或为我指明正确的方向如何使用 promise all 实现回调将不胜感激,也许 promise all 不是为了做到这一点而设计的,我不确定。

谢谢

感谢@nobody 的工作代码;)

let AWS = require("aws-sdk");

const fs = require('fs');

const path = require('path');

const s3 = new AWS.S3();

const params = [];

fs.readdirSync('/Users/dave/Desktop/uploadit').forEach(file => {

    const {
        ext,
        name,
        dir
    } = path.parse(file);

    let fl = name.replace(/[^a-z0-9/]/gi, '_').toLowerCase();

    params.push({ 
        Bucket: 's3b-south-amercia', 
        Key: fl + ext, 
        Body: fs.readFileSync('/Users/dave/Desktop/uploadit/' + file)
    });

});

var progress = 1;

var total_files = params.length;

console.log('total_files', total_files);

const onProgress = async promise => {

    const result = await promise;

    console.log(progress / total_files * 100 + '%');

    progress++;
    
    return result;

};

// Start function
const start = async function(a, b) {
    
    console.time('test');

    const responses = await Promise.all(
        params.map(param => onProgress(s3.upload(param).promise()))
    );
    /*const responses = await Promise.all(
        params.map(param => s3.upload(param).promise())
    );*/

    console.timeEnd('test');

}

// Call start
start();

// time aws s3 cp /Users/dave/Desktop/uploadit s3://s3b-south-amercia/ --recursive
// AWS CLI 26.295 / 24.684s
// AWS NODE 27.859s / 20.483

更新:

当您在包含大量文件的文件夹上运行此代码时通知任何使用此代码的人,您几乎肯定会遇到此错误。

RequestTimeTooSkewed:请求时间与当前时间相差过大

我在这里创建了一张票和一个解决方法。

https://github.com/aws/aws-sdk-js/issues/3757

但希望很快就会对 SDK 进行修复。

标签: javascriptnode.jsamazon-web-servicesamazon-s3promise

解决方案


你可以用你自己的函数来包装s3.upload,只要它返回原始响应,你就可以在Promise.all.

const onDone = async promise => {
  const result = await promise;
  console.log("File upload complete");
  // Or add +1 to some variable to calculate percentage of completed uploads
  return result;
};

const responses = await Promise.all(
  params.map(param => onDone(s3.upload(param).promise()))
);

推荐阅读