使用 Promise.all 为 AWS Node.js 上传创建进度条
Creating a progress bar for AWS Node.js upload using Promise.all
我一直在研究以下代码,试图将我当前的 AWS 上传器减少到几行代码。这段代码效果很好,但我真的需要一个进度指示器来监控上传进度,因为对于较大的文件或文件夹上传,用户不知道需要多长时间。
我是 promise await 的新手,我当前的代码使用回调。
我在这里看到这段代码。
是否可以为每个上传成功的文件回调?这样我就可以得到所有要上传的文件的总长度,并根据该长度输出一个进度。
这是我当前的代码。
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 很快就会得到修复。
你可以用你自己的函数包装 s3.upload
,只要 returns 原始响应你就会有一个钩子进入 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()))
);
这是一个使用自定义承诺库的示例,该库支持开箱即用的高级进度捕获(并发限制只是为了演示而添加):
Live sandbox
import { CPromise } from "c-promise2";
(async () => {
const results = await CPromise.all(
[
"filename1.txt",
"filename2.txt",
"filename3.txt",
"filename4.txt",
"filename5.txt",
"filename6.txt",
"filename7.txt"
],
{
async mapper(filename) {
console.log(`load and push file [${filename}]`);
// your async code here to upload a single file
return CPromise.delay(1000, `operation result for [${filename}]`);
},
concurrency: 2
}
).progress((p) => {
console.warn(`Uploading: ${(p * 100).toFixed(1)}%`);
});
console.log(results);
})();
我一直在研究以下代码,试图将我当前的 AWS 上传器减少到几行代码。这段代码效果很好,但我真的需要一个进度指示器来监控上传进度,因为对于较大的文件或文件夹上传,用户不知道需要多长时间。
我是 promise await 的新手,我当前的代码使用回调。
我在这里看到这段代码。
是否可以为每个上传成功的文件回调?这样我就可以得到所有要上传的文件的总长度,并根据该长度输出一个进度。
这是我当前的代码。
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 很快就会得到修复。
你可以用你自己的函数包装 s3.upload
,只要 returns 原始响应你就会有一个钩子进入 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()))
);
这是一个使用自定义承诺库的示例,该库支持开箱即用的高级进度捕获(并发限制只是为了演示而添加): Live sandbox
import { CPromise } from "c-promise2";
(async () => {
const results = await CPromise.all(
[
"filename1.txt",
"filename2.txt",
"filename3.txt",
"filename4.txt",
"filename5.txt",
"filename6.txt",
"filename7.txt"
],
{
async mapper(filename) {
console.log(`load and push file [${filename}]`);
// your async code here to upload a single file
return CPromise.delay(1000, `operation result for [${filename}]`);
},
concurrency: 2
}
).progress((p) => {
console.warn(`Uploading: ${(p * 100).toFixed(1)}%`);
});
console.log(results);
})();