如何使用node.js,Express和knox将文件从浏览器上传到Amazon S3?

时间:2011-07-21 09:47:30

标签: node.js upload amazon-s3 express

我正在尝试找到一些使用node.js,Express和knox的示例代码。

Knox的文档仅提供了如何上传已存储在文件系统中的文件的明确示例。 https://github.com/learnboost/knox#readme

此外,还有一些关于如何直接上传文件以表达并保存到文件系统的简单教程(即使在Express本身)。

我遇到的问题是一个示例,它允许您将客户端上载上传到节点服务器,并将数据直接流式传输到S3,而不是先存储在本地文件系统中。

有人能指出我要包含此类信息的要点或其他示例吗?

6 个答案:

答案 0 :(得分:13)

所有以前的答案都涉及让上传通过您的node.js服务器,这是低效且不必要的。您的节点服务器无需处理上传文件的带宽或处理,因为Amazon S3允许直接从浏览器上传

查看此博文:http://blog.tcs.de/post-file-to-s3-using-node/

我没有尝试过那里列出的代码,但是看了之后,它看起来很稳固,我将在不久之后尝试实施它。广告会根据我的发现更新这个答案。

答案 1 :(得分:4)

以下是使用multipartyknox直接流式传输到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

的示例

答案 2 :(得分:1)

节点/快速代码不适用于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
  });
});

答案 3 :(得分:0)

*更新*

截至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 }));
  // ...
});

答案 4 :(得分:-1)

connect-stream-s3库可以将所有表单文件作为中间件的一部分上传到S3,因此您不必自己做任何逻辑。它需要express.bodyParser()才能使它正常工作,但我正在开发一个版本,它会在写入磁盘之前将文件直接传输到Amazon S3:

请告诉我你是怎么过的。一旦你进入你的页面处理程序,希望它比你自己做的麻烦少得多。 :)

答案 5 :(得分:-1)

我这是直接从Jquery文件上传插件上传到S3,文件是公共的 - 它应该指向正确的方向。

https://gist.github.com/3995819