私は、要件のあるノードjsサーバーを使用してAmazon S3でファイルをストリーミングするためのソリューションを見つけようとしています。
その場合、S3資格情報を共有する必要があるため、ブラウザーからの直接ファイルアップロードは使用しません。ノードjsサーバーからファイルをアップロードするもう1つの理由は、ファイルをアップロードする前に何らかの認証を適用する必要がある場合があることです。
Node-multipartyを使用してこれを達成しようとしました。しかし、期待どおりに機能していませんでした。私の解決策と問題は https://github.com/andrewrk/node-multiparty/issues/49 で確認できます。小さなファイルでは正常に動作しますが、サイズが15MBのファイルでは失敗します。
解決策や代替案はありますか?
nodejs用の公式Amazon SDK でストリーミングを使用できるようになりました。さらに素晴らしいことは、事前にファイルサイズを知らなくてもできることです。ストリームをBody
として渡すだけです:
var fs = require('fs');
var zlib = require('zlib');
var body = fs.createReadStream('bigfile').pipe(zlib.createGzip());
var s3obj = new AWS.S3({params: {Bucket: 'myBucket', Key: 'myKey'}});
s3obj.upload({Body: body})
.on('httpUploadProgress', function(evt) { console.log(evt); })
.send(function(err, data) { console.log(err, data) });
https://www.npmjs.org/package/streaming-s を試してください。
いくつかの大きなファイルを並行して(> 500Mb)アップロードするために使用しましたが、非常にうまく機能しました。それは非常に構成可能で、アップロード統計を追跡することもできます。オブジェクトの合計サイズを知る必要はなく、ディスクには何も書き込まれません。
作業中のプロジェクトで s3-upload-stream モジュールを使用しています here 。
彼の http-framework リポジトリには@raynosの良い例もいくつかあります。
または、- https://github.com/minio/minio-js をご覧ください。最も一般的に使用されるS3呼び出しを実装する抽象化されたAPIの最小限のセットがあります。
ストリーミングアップロードの例を次に示します。
$ npm install minio
$ cat >> put-object.js << EOF
var Minio = require('minio')
var fs = require('fs')
// find out your s3 end point here:
// http://docs.aws.Amazon.com/general/latest/gr/rande.html#s3_region
var s3Client = new Minio({
url: 'https://<your-s3-endpoint>',
accessKey: 'YOUR-ACCESSKEYID',
secretKey: 'YOUR-SECRETACCESSKEY'
})
var outFile = fs.createWriteStream('your_localfile.Zip');
var fileStat = Fs.stat(file, function(e, stat) {
if (e) {
return console.log(e)
}
s3Client.putObject('mybucket', 'hello/remote_file.Zip', 'application/octet-stream', stat.size, fileStream, function(e) {
return console.log(e) // should be null
})
})
EOF
ここでputObject()は、5MBを超えるファイルサイズの完全に管理された単一関数呼び出しであり、内部で自動的にmultipartを実行します。失敗したアップロードも再開できます。以前にアップロードした部分を確認することにより、中断したところから開始します。
さらに、このライブラリも同型であり、ブラウザでも使用できます。
クライアントからs3に正常にストリーミングできた(メモリやディスクストレージなしで)ことができた場合:
https://Gist.github.com/mattlockyer/532291b6194f6d9ca40cb82564db9d2a
サーバーエンドポイントはreq
がストリームオブジェクトであると想定します。クライアントからFileオブジェクトを送信し、これを最新のブラウザーがバイナリデータとして送信し、ヘッダーにファイル情報セットを追加しました。
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);
}
});
};
はい、ヘッダーにファイル情報を入れると慣習に違反しますが、Gistを見ると、ストリーミングライブラリやmulter、busboyなどを使用して見つけた他のものよりもずっときれいです...
実用主義のために+1、そして彼の助けに@SalehenRahmanに感謝します。