如何使用 node.js、Express 和 knox 将文件从浏览器上传到 Amazon S3? [关闭]
Posted
技术标签:
【中文标题】如何使用 node.js、Express 和 knox 将文件从浏览器上传到 Amazon S3? [关闭]【英文标题】:How to upload a file from the browser to Amazon S3 with node.js, Express, and knox? [closed] 【发布时间】:2011-10-10 02:13:53 【问题描述】:我正在尝试查找一些使用 node.js、Express 和 knox 的示例代码。
Knox 的文档仅给出了如何上传已存储在文件系统中的文件的清晰示例。 https://github.com/learnboost/knox#readme
此外,还有一些简单的教程(甚至在 Express 本身中)关于如何直接上传文件以表达并保存到文件系统。
我很难找到一个示例,它允许您将客户端上传上传到节点服务器并将数据直接流式传输到 S3,而不是先存储在本地文件系统中。
谁能指出包含此类信息的要点或其他示例?
【问题讨论】:
Andrew Barber,怎么不清楚他们在问什么?大多数回答这个问题的人似乎都没有问题理解它。 同意。重量级为什么要关闭一个已有 2 年历史且已更新有价值信息的问题?此外,关闭它会破坏它所获得的 seo 价值。 对我来说这个问题很清楚,如果你不明白这个话题的重点,那可能只是意味着你不应该给出答案,因为你对那个话题不够深入. 【参考方案1】:之前的所有答案都涉及让上传通过您的 node.js 服务器,这是低效且不必要的。您的节点服务器无需处理上传文件的带宽或处理,因为 Amazon S3 允许直接从浏览器上传。
看看这篇博文:http://blog.tcs.de/post-file-to-s3-using-node/
我还没有尝试过那里列出的代码,但是在查看了它之后,它看起来很可靠,我很快就会尝试实现它,广告会用我的发现更新这个答案。
【讨论】:
“之前的所有答案都涉及让上传通过你的 node.js 服务器,这是低效且不必要的。”但在我回答时(2011 年),您的解决方案不可用。但我同意:现在,这是最好的方法。 我正在使用一个 s3“兼容”服务(来自 cloudfoundry 的 vBlob),它不接受 method="post",而只接受 method="put"。有什么想法吗? 在客户端使用亚马逊代码不是不安全吗? 您的 amazon/s3 代码不在客户端,它们保存在服务器端(节点端点进入的地方),并在向 s3 的上传请求发送之前被编码并提供给客户端制作 如果攻击者在客户端代码中使用 amazon id 并耗尽您的存储空间怎么办?【参考方案2】:以下是使用multiparty 和knox 直接流式传输到s3 而不接触硬盘的示例:
var http = require('http')
, util = require('util')
, multiparty = require('multiparty')
, knox = require('knox')
, Batch = require('batch')
, PORT = process.env.PORT || 27372
var s3Client = knox.createClient(
secure: false,
key: process.env.S3_KEY,
secret: process.env.S3_SECRET,
bucket: process.env.S3_BUCKET,
);
var Writable = require('readable-stream').Writable;
util.inherits(ByteCounter, Writable);
function ByteCounter(options)
Writable.call(this, options);
this.bytes = 0;
ByteCounter.prototype._write = function(chunk, encoding, cb)
this.bytes += chunk.length;
cb();
;
var server = http.createServer(function(req, res)
if (req.url === '/')
res.writeHead(200, 'content-type': 'text/html');
res.end(
'<form action="/upload" enctype="multipart/form-data" method="post">'+
'<input type="text" name="path"><br>'+
'<input type="file" name="upload"><br>'+
'<input type="submit" value="Upload">'+
'</form>'
);
else if (req.url === '/upload')
var headers =
'x-amz-acl': 'public-read',
;
var form = new multiparty.Form();
var batch = new Batch();
batch.push(function(cb)
form.on('field', function(name, value)
if (name === 'path')
var destPath = value;
if (destPath[0] !== '/') destPath = '/' + destPath;
cb(null, destPath);
);
);
batch.push(function(cb)
form.on('part', function(part)
if (! part.filename) return;
cb(null, part);
);
);
batch.end(function(err, results)
if (err) throw err;
form.removeListener('close', onEnd);
var destPath = results[0]
, part = results[1];
var counter = new ByteCounter();
part.pipe(counter); // need this until knox upgrades to streams2
headers['Content-Length'] = part.byteCount;
s3Client.putStream(part, destPath, headers, function(err, s3Response)
if (err) throw err;
res.statusCode = s3Response.statusCode;
s3Response.pipe(res);
console.log("https://s3.amazonaws.com/" + process.env.S3_BUCKET + destPath);
);
part.on('end', function()
console.log("part end");
console.log("size", counter.bytes);
);
);
form.on('close', onEnd);
form.parse(req);
else
res.writeHead(404, 'content-type': 'text/plain');
res.end('404');
function onEnd()
throw new Error("no uploaded file");
);
server.listen(PORT, function()
console.info('listening on http://0.0.0.0:'+PORT+'/');
);
示例取自https://github.com/superjoe30/node-multiparty/blob/master/examples/s3.js
【讨论】:
感谢您,希望您能在此处为我的问题提供帮助:***.com/q/21873561/971592 @andrewrk 在上面提到的答案中,我应该如何在文件上传完成之前停止它。示例:文件当前正在上传,我意识到文件太大,所以我想通过发送适当的消息来停止上传。我的节点服务器挂起,因为当我希望停止上传时没有发回正确的响应。 ***.com/questions/33452952/…【参考方案3】:node/express 代码不适用于 nodejs v0.4.7
这里是 nodejs v0.4.7 的更新代码
app.post('/upload', function (req, res)
// connect-form additions
req.form.complete(function (err, fields, files)
// here lies your uploaded file:
var path = files['upload-file']['path'];
// do knox stuff here
);
);
【讨论】:
【参考方案4】:* 更新 *
截至 2009 年年中,亚马逊支持 CORS,并且不再需要通过您的 node.js 服务器上传。您可以直接将文件上传到 S3。
在“connect-form”模块的帮助下,您可以将文件上传到您的服务器(通过普通的多部分 FORM),然后处理 S3 的东西......
<form action="/upload" method="POST" id="addContentForm" enctype="multipart/form-data">
<p><label for="media">File<br/><input type="file" name="media" /></label></p>
<p><button type="submit">upload</button></p>
</form>
节点/快递代码:
app.post('/upload', function (req, res)
// connect-form additions
req.form.complete(function (err, fields, files)
// here lies your uploaded file:
var path = files['media']['path'];
// do knox stuff here
);
);
您必须将以下行添加到应用配置中:
app.configure(function()
// rest of the config stuff ...
app.use(form( keepExtensions: true ));
// ...
);
【讨论】:
有趣!在考虑客户端直接上传到 S3 时,我们必须采取哪些安全预防措施?我想我们不想给任何人和每个人这种能力。谢谢:) talentedmrjones 提供了一个容易受到中间人攻击的解决方案。这里给出了另一种解决方案terlici.com/2015/05/23/uploading-files-s3.html,这是正确的。但它有一些限制,比如你不能提及文件大小等。【参考方案5】:connect-stream-s3 库可以将您的所有表单文件作为中间件的一部分上传到 S3,因此您不必自己执行任何逻辑。它目前需要 express.bodyParser() 才能工作,但我正在开发一个版本,该版本将在写入磁盘之前将文件直接流式传输到 Amazon S3:
https://github.com/appsattic/connect-stream-s3请告诉我你的进展如何。希望一旦你在你的页面处理程序中,它比你自己做的麻烦少得多。 :)
【讨论】:
【参考方案6】:我这样做是为了直接从 Jquery File Upload 插件上传到 S3,文件是公开的 - 它应该为您指明正确的方向。
https://gist.github.com/3995819
【讨论】:
以上是关于如何使用 node.js、Express 和 knox 将文件从浏览器上传到 Amazon S3? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Express 和 Node.js 从表单发送参数
如何使用 Express JS/Railway JS (Node.JS) 生成 JSON