如何使用 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 从表单发送参数

node.js 和 express:如何等待 udp 响应

如何使用 node.js/express 中止请求?

如何使用 Express JS/Railway JS (Node.JS) 生成 JSON

会话如何在 Express.js 和 Node.js 中工作?

如何使用在 node.js 上的方法和 express 来获取更新信息