我正在尝试使用aws sdk或knox将通过表单提交的文件直接流式上传到Amazon S3 bucket。表单处理是通过强大的。
我的问题是:如何正确地使用aws sdk(或knox)中的强大功能,使用这些库的每个最新功能来处理流?
我知道这里已经有人以不同的方式问过这个话题,比如:
然而,我认为答案有点过时和/或偏离主题(例如。CORS支持,出于各种原因,我现在不想使用它)和/或,最重要的是,没有提到AWS-sdk(参见:https://github.com/aws/aws-sdk-js/issues/13#issuecomment-16085442)或Knox(特别是putStream()或其可读tream.pipe(req)变体的最新功能,两者都在文档中解释)。
经过几个小时的挣扎,我得出结论,我需要一些帮助(免责声明:我对溪流还是个新手)。
HTML格式:
<form action="/uploadPicture" method="post" enctype="multipart/form-data">
<input name="picture" type="file" accept="image/*">
<input type="submit">
</form>
Express body Parser中间件是这样配置的:
app.use(express.bodyParser({defer: true}))
请求后处理程序:
uploadPicture = (req, res, next) ->
form = new formidable.IncomingForm()
form.parse(req)
form.onPart = (part) ->
if not part.filename
# Let formidable handle all non-file parts (fields)
form.handlePart(part)
else
handlePart(part, form.bytesExpected)
handlePart = (part, fileSize) ->
# aws-sdk version
params =
Bucket: "mybucket"
Key: part.filename
ContentLength: fileSize
Body: part # passing stream object as body parameter
awsS3client.putObject(params, (err, data) ->
if err
console.log err
else
console.log data
)
但是,我得到了以下错误:
{[RequestTimeout:您与服务器的套接字连接在超时期间未被读取或写入。空闲连接将被关闭。]
消息:“您与服务器的套接字连接在超时期间未被读取或写入。”。空闲连接将被关闭。“,代码:'RequestTimeout',名称:'RequestTimeout',状态代码:400,可重试:false}
以这种方式定制的handlePart()函数的Knox版本也悲惨地失败了:
handlePart = (part, fileSize) ->
headers =
"Content-Length": fileSize
"Content-Type": part.mime
knoxS3client.putStream(part, part.filename, headers, (err, res) ->
if err
console.log err
else
console.log res
)
我也得到了一个大的res对象与400状态代码的地方。
在这两种情况下,区域都配置为eu-west-1。
补充说明:
节点
最新强大的从npm(1.0.14)
npm最新的aws sdk(1.3.1)
npm的最新knox(0.8.3)
因为这篇帖子太老了,我相信现在支持直接流媒体,所以我花了很多时间阅读关于这个话题的过时答案。。。
如果它对任何人都有帮助,那么我可以直接从客户端流式传输到s3,而无需安装软件包:
https://gist.github.com/mattlockyer/532291b6194f6d9ca40cb82564db9d2a
服务器假定req
是一个流对象,在我的例子中,xhr(send)中使用了一个文件对象,它将在现代浏览器中发送二进制数据。
const fileUploadStream = (req, res) => {
//get "body" args from header
const { id, fn } = JSON.parse(req.get('body'));
const Key = id + '/' + fn; //upload to s3 folder "id" with filename === fn
const params = {
Key,
Bucket: bucketName, //set somewhere
Body: req, //req is a stream
};
s3.upload(params, (err, data) => {
if (err) {
res.send('Error Uploading Data: ' + JSON.stringify(err) + '\n' + JSON.stringify(err.stack));
} else {
res.send(Key);
}
});
};
是的,它打破了惯例,但如果你看一下要点,它比我发现的依赖其他软件包的任何东西都要干净得多。
1表示实用主义,并感谢@SalehenRahman的帮助。
使用AWS S3的多部分上传(s3上传流作为工作模块)和节点强大的可读流,您可以像这样通过管道将流上传:
var formidable = require('formidable');
var http = require('http');
var util = require('util');
var AWS = require('aws-sdk');
var config = require('./config');
var s3 = new AWS.S3({
accessKeyId: config.get('S3_ACCESS_KEY'),
secretAccessKey: config.get('S3_SECRET_KEY'),
apiVersion: '2006-03-01'
});
var s3Stream = require('s3-upload-stream')(s3);
var bucket = 'bucket-name';
var key = 'abcdefgh';
http.createServer(function(req, res) {
if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
var form = new formidable.IncomingForm();
form.on('progress', function(bytesReceived, bytesExpected) {
//console.log('onprogress', parseInt( 100 * bytesReceived / bytesExpected ), '%');
});
form.on('error', function(err) {
console.log('err',err);
});
// This 'end' is for the client to finish uploading
// upload.on('uploaded') is when the uploading is
// done on AWS S3
form.on('end', function() {
console.log('ended!!!!', arguments);
});
form.on('aborted', function() {
console.log('aborted', arguments);
});
form.onPart = function(part) {
console.log('part',part);
// part looks like this
// {
// readable: true,
// headers:
// {
// 'content-disposition': 'form-data; name="upload"; filename="00video38.mp4"',
// 'content-type': 'video/mp4'
// },
// name: 'upload',
// filename: '00video38.mp4',
// mime: 'video/mp4',
// transferEncoding: 'binary',
// transferBuffer: ''
// }
var start = new Date().getTime();
var upload = s3Stream.upload({
"Bucket": bucket,
"Key": part.filename
});
// Optional configuration
//upload.maxPartSize(20971520); // 20 MB
upload.concurrentParts(5);
// Handle errors.
upload.on('error', function (error) {
console.log('errr',error);
});
upload.on('part', function (details) {
console.log('part',details);
});
upload.on('uploaded', function (details) {
var end = new Date().getTime();
console.log('it took',end-start);
console.log('uploaded',details);
});
// Maybe you could add compress like
// part.pipe(compress).pipe(upload)
part.pipe(upload);
};
form.parse(req, function(err, fields, files) {
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
return;
}
// show a file upload form
res.writeHead(200, {'content-type': 'text/html'});
res.end(
'<form action="/upload" enctype="multipart/form-data" method="post">'+
'<input type="text" name="title"><br>'+
'<input type="file" name="upload" multiple="multiple"><br>'+
'<input type="submit" value="Upload">'+
'</form>'
);
}).listen(8080);
根据强大的创造者的说法,直接流式传输到亚马逊S3是不可能的:
S3API要求您在创建新文件时提供其大小。在完全接收多部分/表单数据文件之前,这些信息不适用于多部分/表单数据文件。这意味着流媒体是不可能的。
事实上,form.bytes预期是指整个表单的大小,而不是单个文件的大小。
因此,在上传到S3之前,数据必须先到达服务器上的内存或磁盘。
问题内容: 我正在尝试使用aws-sdk或knox将通过表单提交的文件直接上传到Amazon S3存储桶。表单处理非常强大。 我的问题是:如何使用这些库的最新功能来正确处理aws-sdk(或knox)的强大功能? 但是,我认为答案有点过时和/或偏离主题(例如,出于各种原因,我现在不希望使用CORS支持),和/或最重要的是,请勿参考的最新功能。要么是aws- sdk(请参阅:https : //gi
我正在使用Node上传mp3文件到亚马逊S3。当我上传它时,文件大小是9.0字节,当我转到公共url时,音频文件不会播放。这就是我所拥有的, 我也将权限设置为公共访问。
问题内容: 我正在尝试找到一些利用node.js,Express和knox的示例代码。 Knox的文档仅给出有关如何上传已存储在文件系统中的文件的清晰示例。https://github.com/learnboost/knox#readme 此外,还有许多简单的教程(甚至在Express本身中),介绍了如何直接上传文件以表达并保存到文件系统。 我遇到的麻烦是一个示例,该示例使您可以将客户端上传的文件
问题内容: 尝试将文件上传到S3存储桶时遇到问题。一切正常,除了我的文件参数似乎不合适。我正在使用Amazon S3 SDK从Node.js上载到S3。 这些是我的路线设置: 这是items.upload()函数: 将param 设置为类似字符串的效果很好。根据doc,param必须获取 (缓冲区,类型数组,Blob,字符串,ReadableStream)对象数据。 但是,上传文件对象失败,并显示
我正在尝试复制一个邮递员放置请求,其中它正在代码给出的S3位置上传csv文件。 网址就像https://us-east-1-e9qpbo283.s3.amazonaws.com/bulk-bucket/a4894e7b-7e42-4fcc-9f84-e7n00db6d581/input/file 查询参数为
问题内容: 我需要创建一个Zip文件,该文件由位于我的s3存储桶中的一系列文件(视频和图像)组成。 目前使用以下代码的问题是,我很快达到了Lambda的内存限制。 使用Lambda是否有可能,还是我应该采用其他方法? 是否可以即时写入压缩的zip文件,从而在某种程度上消除内存问题,还是我需要在压缩之前收集文件? 任何帮助将非常感激。 问题答案: 好的,我今天必须这样做,并且可以正常工作。直接缓冲区