一次将大量文件上传到 AWS S3

Jam*_* H. 4 file-upload amazon-s3 amazon-web-services node.js express

我有一个应用程序,需要上传超过100,000 files1MB每个)到S3 Bucket. 我知道 S3 有上传大文件的 API,但想知道他们是否有上传大量文件的 API。

我目前正在使用putObject并尝试使用uploadAPI 将我的文件上传到 S3。问题是上传时间太长(浏览器超时后完成)并使用大量内存(超过512MB允许的限制)。

保存文件的代码:

saveFile: async (fileUrl, data) => {
    await s3.putObject({
        Bucket: bucket,
        Key: fileUrl,
        Body: JSON.stringify(data)
    }).promise();
},
Run Code Online (Sandbox Code Playgroud)

在另一个地方,我把它放在这样saveFile的循环中:

for (let file of files) {
    await saveFile(file.url, file.data);
}
Run Code Online (Sandbox Code Playgroud)

我搜索了一个解决方案,发现stream可能有助于减少内存需求,但我想知道时间上有什么不同吗?如果是,我该如何实现?谢谢。

Sim*_*nti 6

我通常更喜欢使用托管上传 API,而不是 putObject 方法。它处理带有 multiplart 上传的大文件,此外它还支持流(您不能将流与 putObject 一起使用,因为该 API 需要总文件大小)。

例如,从节点:

const fs = require('fs');
const AWS = require('aws-sdk');
const s3 = new AWS.S3({});

s3.upload({
  Bucket: 'xxx',
  Key: 'fileName.png',
  Body: fs.createReadStream('/home/bar/Desktop/fileName.png')
}).promise(); // or callback
Run Code Online (Sandbox Code Playgroud)

这可能会解决您的内存相关问题,但可能不会加快上传速度。for循环的问题在于它会依次上传对象,一个接一个。相反,您可以使用 a await Promise.all([/* your list*/].map(/* ... */)),它将并行执行所有上传 - 但是 - 100,000 到目前为止是一个太大的数字。

我建议使用像async这样的库,它有很多有用的方法来处理异步操作组。例如,您可以使用cargoorqueue方法,您的代码将如下所示:

const PARALLEL_UPLOADS = 10;
const q = async.queue((task, callback) => {
  s3.upload({
    Bucket: 'xxx',
    Key: task.dest,
    Body: fs.createReadStream(task.src)
  }, callback)
}, PARALLEL_UPLOADS);

q.drain = function() {
    console.log('all items have been processed');
};

q.push([
    { src: 'image1.png', dest: 'images/image1.png' },
    { src: 'image2.png', dest: 'images/image2.png' },
]);
Run Code Online (Sandbox Code Playgroud)

这将上传您的所有文件,最多可同时上传 10 个项目。

希望这可以帮助,