web-dev-qa-db-ja.com

node.js、Express、knoxを使用してブラウザからAmazon S3にファイルをアップロードするにはどうすればよいですか?

Node.js、Express、およびknoxを利用するサンプルコードを見つけようとしています。

Knoxのドキュメントには、ファイルシステムにすでに保存されているファイルをアップロードする方法の明確な例のみが記載されています。 https://github.com/learnboost/knox#readme

さらに、ファイルを直接アップロードして表現し、ファイルシステムに保存する方法について、(Express自体でも)いくつかの簡単なチュートリアルがあります。

私が見つけにくいのは、クライアントのアップロードをノードサーバーにアップロードし、最初にローカルファイルシステムに保存するのではなく、データをS3に直接ストリーミングできる例です。

誰かが私にこの種の情報を含む要点または他の例を指摘できますか?

21
Geuis

これまでのすべての回答には、アップロードがnode.jsサーバーを通過することが含まれていますが、これは非効率的で不要です。 Amazon S3ではブラウザから直接アップロードできるため、ノードサーバーはアップロードされたファイルの帯域幅や処理を処理する必要はありません。

このブログ投稿をご覧ください: http://blog.tcs.de/post-file-to-s3-using-node/

私はそこにリストされているコードを試していませんが、それを調べたところ、しっかりしているように見えます。まもなく実装を試みます。広告でこの回答を私の調査結果で更新します。

13
talentedmrjones

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 からの例

4
andrewrk

node/expressコードはnodejsv0.4.7では機能しません

これがnodejsv0.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
  });
});
1
heisthedon

*更新*

2009年半ばの時点で、Amazonは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 }));
  // ...
});
0
pkyeck