Node JS - 将数据从 Busboy 流式传输到 AWS S3
Node JS - Stream data from Busboy to AWS S3
我正在尝试通过 ec2 将文件上传到 s3。
我的第一种方法是 - 将文件完全上传到 ec2,然后将该文件上传到 s3。这种方法不好,因为从 ec2 到 s3 的传输时间是浪费时间。
目前我正在尝试使用 busboy 上传流 到 s3 上传流 这样上传到 ec2 然后 ec2 到 s3 将是与 s3 同时完成 "upload" 方法支持流作为上传主体。
这是我的代码 -
router.post('/s3StreamUpload', function(req, res, next) {
var busboy = new Busboy({headers: req.headers});
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
console.log('Before Upload: ' + new Date());
console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype);
var s3 = new AWS.S3({
params: {Bucket: 'sswa', Key: filename, Body: file},
options: {partSize: 5 * 1024 * 1024, queueSize: 10} // 5 MB
});
s3.upload().on('httpUploadProgress', function (evt) {
console.log(evt);
}).send(function (err, data) {
console.log('After Upload: ' + new Date());
console.log(err, data);
});
});
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) {
console.log('Field [' + fieldname + ']: value: ' + inspect(val));
});
busboy.on('finish', function() {
console.log('Done parsing form!');
res.writeHead(303, { Connection: 'close', Location: '/' });
res.end();
});
req.pipe(busboy);
});
我怀疑它是否真的以流的形式同时上传到 s3?这种方法有什么缺点吗?
为了测试多部分流式上传到 S3 是否有效,我在三个执行点记录了时间 -
- 开始从客户端上传之前 (uploadStartTime)
- 上传到EC2后(busboyFinishTime)
- 转移到S3后(s3UploadFinishTime)
然后我 运行 来自 EC2。上传各种长度的视频文件(36.1 MB、33.3 MB、52.5 MB)后,我观察到每上传 5MB(如我定义的)到 EC2,部分就会立即传输到 S3。将部件上传到 S3 时,您将看到以下行的日志。它将显示文件部分上传进度和部分编号。
console.log(evt);
所有三个上传 busboyFinishTime 和 s3UploadFinishTime 相同或几乎没有 1 秒的差异。
示例:
上传 52.5 MB 时
{
"uploadStartTime": "2016-04-28T14:19:51.365Z",
"busboyFinishTime": "2016-04-28T14:22:26.292Z",
"s3UploadFinishTime": "2016-04-28T14:22:26.558Z"
}
完整代码:
router.post('/s3StreamUpload', function(req, res, next) {
var busboy = new Busboy({headers: req.headers});
var uploadStartTime = new Date(),
busboyFinishTime = null,
s3UploadFinishTime = null;
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype);
var s3 = new AWS.S3({
params: {Bucket: 'sswa', Key: filename, Body: file},
options: {partSize: 5 * 1024 * 1024, queueSize: 10} // 5 MB
});
s3.upload().on('httpUploadProgress', function (evt) {
console.log(evt);
}).send(function (err, data) {
s3UploadFinishTime = new Date();
if(busboyFinishTime && s3UploadFinishTime) {
res.json({
uploadStartTime: uploadStartTime,
busboyFinishTime: busboyFinishTime,
s3UploadFinishTime: s3UploadFinishTime
});
}
console.log(err, data);
});
});
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) {
console.log('Field [' + fieldname + ']: value: ' + inspect(val));
});
busboy.on('finish', function() {
console.log('Done parsing form!');
busboyFinishTime = new Date();
if(busboyFinishTime && s3UploadFinishTime) {
res.json({
uploadStartTime: uploadStartTime,
busboyFinishTime: busboyFinishTime,
s3UploadFinishTime: s3UploadFinishTime
});
}
});
req.pipe(busboy);
});
根据我的观察,我确信这是使用部署在 EC2 上的 REST API 通过 EC2 将文件上传到 S3 的最佳解决方案之一。
您是否尝试直接从浏览器上传到 S3?如果是这样,您可以使用 presigned-put 直接浏览器到 S3 上传。
这就是使用 minio-js
生成预签名 PUT url 的方式
s3Client.presignedPutObject('my-bucketname', 'my-objectname', 1000, function(e, presignedUrl) {
if (e) return console.log(e)
console.log(presignedUrl)
})
现在您将这个预签名 URL 传递给浏览器客户端,它可以使用 XMLHttpRequest 直接将文件 PUT 到 S3。
我正在尝试通过 ec2 将文件上传到 s3。 我的第一种方法是 - 将文件完全上传到 ec2,然后将该文件上传到 s3。这种方法不好,因为从 ec2 到 s3 的传输时间是浪费时间。
目前我正在尝试使用 busboy 上传流 到 s3 上传流 这样上传到 ec2 然后 ec2 到 s3 将是与 s3 同时完成 "upload" 方法支持流作为上传主体。
这是我的代码 -
router.post('/s3StreamUpload', function(req, res, next) {
var busboy = new Busboy({headers: req.headers});
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
console.log('Before Upload: ' + new Date());
console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype);
var s3 = new AWS.S3({
params: {Bucket: 'sswa', Key: filename, Body: file},
options: {partSize: 5 * 1024 * 1024, queueSize: 10} // 5 MB
});
s3.upload().on('httpUploadProgress', function (evt) {
console.log(evt);
}).send(function (err, data) {
console.log('After Upload: ' + new Date());
console.log(err, data);
});
});
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) {
console.log('Field [' + fieldname + ']: value: ' + inspect(val));
});
busboy.on('finish', function() {
console.log('Done parsing form!');
res.writeHead(303, { Connection: 'close', Location: '/' });
res.end();
});
req.pipe(busboy);
});
我怀疑它是否真的以流的形式同时上传到 s3?这种方法有什么缺点吗?
为了测试多部分流式上传到 S3 是否有效,我在三个执行点记录了时间 -
- 开始从客户端上传之前 (uploadStartTime)
- 上传到EC2后(busboyFinishTime)
- 转移到S3后(s3UploadFinishTime)
然后我 运行 来自 EC2。上传各种长度的视频文件(36.1 MB、33.3 MB、52.5 MB)后,我观察到每上传 5MB(如我定义的)到 EC2,部分就会立即传输到 S3。将部件上传到 S3 时,您将看到以下行的日志。它将显示文件部分上传进度和部分编号。
console.log(evt);
所有三个上传 busboyFinishTime 和 s3UploadFinishTime 相同或几乎没有 1 秒的差异。
示例: 上传 52.5 MB 时
{
"uploadStartTime": "2016-04-28T14:19:51.365Z",
"busboyFinishTime": "2016-04-28T14:22:26.292Z",
"s3UploadFinishTime": "2016-04-28T14:22:26.558Z"
}
完整代码:
router.post('/s3StreamUpload', function(req, res, next) {
var busboy = new Busboy({headers: req.headers});
var uploadStartTime = new Date(),
busboyFinishTime = null,
s3UploadFinishTime = null;
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype);
var s3 = new AWS.S3({
params: {Bucket: 'sswa', Key: filename, Body: file},
options: {partSize: 5 * 1024 * 1024, queueSize: 10} // 5 MB
});
s3.upload().on('httpUploadProgress', function (evt) {
console.log(evt);
}).send(function (err, data) {
s3UploadFinishTime = new Date();
if(busboyFinishTime && s3UploadFinishTime) {
res.json({
uploadStartTime: uploadStartTime,
busboyFinishTime: busboyFinishTime,
s3UploadFinishTime: s3UploadFinishTime
});
}
console.log(err, data);
});
});
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) {
console.log('Field [' + fieldname + ']: value: ' + inspect(val));
});
busboy.on('finish', function() {
console.log('Done parsing form!');
busboyFinishTime = new Date();
if(busboyFinishTime && s3UploadFinishTime) {
res.json({
uploadStartTime: uploadStartTime,
busboyFinishTime: busboyFinishTime,
s3UploadFinishTime: s3UploadFinishTime
});
}
});
req.pipe(busboy);
});
根据我的观察,我确信这是使用部署在 EC2 上的 REST API 通过 EC2 将文件上传到 S3 的最佳解决方案之一。
您是否尝试直接从浏览器上传到 S3?如果是这样,您可以使用 presigned-put 直接浏览器到 S3 上传。
这就是使用 minio-js
生成预签名 PUT url 的方式s3Client.presignedPutObject('my-bucketname', 'my-objectname', 1000, function(e, presignedUrl) {
if (e) return console.log(e)
console.log(presignedUrl)
})
现在您将这个预签名 URL 传递给浏览器客户端,它可以使用 XMLHttpRequest 直接将文件 PUT 到 S3。