Node.jsを使用して、画像を取得し、AmazonS3バケットにアップロードしようとしています。最後に、画像をS3にプッシュして、そのS3 URLにアクセスし、ブラウザーで画像を表示できるようにしたいと思います。 Curlクエリを使用して、画像を本文としてHTTP POSTリクエストを実行しています。
curl -kvX POST --data-binary "@test.jpg" 'http://localhost:3031/upload/image'
次に、Node.js側で、これを行います。
exports.pushImage = function(req, res) {
var image = new Buffer(req.body);
var s3bucket = new AWS.S3();
s3bucket.createBucket(function() {
var params = {Bucket: 'My/bucket', Key: 'test.jpg', Body: image};
// Put the object into the bucket.
s3bucket.putObject(params, function(err) {
if (err) {
res.writeHead(403, {'Content-Type':'text/plain'});
res.write("Error uploading data");
res.end()
} else {
res.writeHead(200, {'Content-Type':'text/plain'});
res.write("Success");
res.end()
}
});
});
};
Amazon S3に示されているように、私のファイルは0バイトです。 Node.jsを使用してバイナリファイルをS3にプッシュできるようにするにはどうすればよいですか?バイナリデータとバッファで何が間違っていますか?
更新:
私は自分が何をする必要があるかを知りました。 curlクエリは、最初に変更する必要があるものです。これは機能しているものです:
curl -kvX POST -F foobar=@my_image_name.jpg 'http://localhost:3031/upload/image'
次に、ストリームに変換する行を追加しました。これは作業コードです:
exports.pushImage = function(req, res) {
var image = new Buffer(req.body);
var s3bucket = new AWS.S3();
s3bucket.createBucket(function() {
var bodyStream = fs.createReadStream(req.files.foobar.path);
var params = {Bucket: 'My/bucket', Key: 'test.jpg', Body: bodyStream};
// Put the object into the bucket.
s3bucket.putObject(params, function(err) {
if (err) {
res.writeHead(403, {'Content-Type':'text/plain'});
res.write("Error uploading data");
res.end()
} else {
res.writeHead(200, {'Content-Type':'text/plain'});
res.write("Success");
res.end()
}
});
});
};
したがって、ファイルをAPIエンドポイントにアップロードし(Node.jsとExpressを使用)、APIがそのファイルをAmazon S3にプッシュするためには、最初にPOSTリクエストを実行する必要があります。 「files」フィールドにデータが入力されます。ファイルはAPI側に配置され、おそらくtmpディレクトリにあります。AmazonのS3 putObjectメソッドにはStreamが必要なため、「fs」モジュールにパスを指定して読み取りストリームを作成する必要があります。アップロードされたファイルが存在します。
これがデータをアップロードする適切な方法かどうかはわかりませんが、機能します。リクエスト本文内にバイナリデータをPOSTして、APIにS3に送信させる方法があるかどうか誰かが知っていますか?マルチパートアップロードの違いはよくわかりませんvs標準POST本体へ。
S3ドキュメントに記載されているようにヘッダーにcontent-lengthを渡す必要があると思います: http://docs.aws.Amazon.com/AmazonS3/latest/API/RESTObjectPUT.html
アセットをS3にプッシュすることにかなりの時間を費やした後、私はAwsSumライブラリを使用することになり、本番環境で優れた結果が得られました。
https://github.com/awssum/awssum-Amazon-s3/
(AWS認証情報の設定に関するドキュメントを参照してください)
例:
var fs = require('fs');
var bucket_name = 'your-bucket name'; // AwsSum also has the API for this if you need to create the buckets
var img_path = 'path_to_file';
var filename = 'your_new_filename';
// using stat to get the size to set contentLength
fs.stat(img_path, function(err, file_info) {
var bodyStream = fs.createReadStream( img_path );
var params = {
BucketName : bucket_name,
ObjectName : filename,
ContentLength : file_info.size,
Body : bodyStream
};
s3.putObject(params, function(err, data) {
if(err) //handle
var aws_url = 'https://s3.amazonaws.com/' + DEFAULT_BUCKET + '/' + filename;
});
});
更新
したがって、Formidable上に構築されたExpressやConnectなどを使用している場合、Formidableはファイルをディスクに書き込むため、ファイルストリームにアクセスできません。したがって、クライアント側でのアップロード方法に応じて、画像はreq.body
またはreq.files
のいずれかになります。私の場合、Expressを使用し、クライアント側では他のデータも投稿するので、画像には独自のパラメーターがあり、req.files.img_data
としてアクセスされます。どのようにアクセスしても、そのパラメータは上記の例でimg_path
として渡すものです。
トリッキーなファイルをストリーミングする必要がある場合/ストリーミングしたい場合は確かに可能ですが、画像を操作していない場合は、ここで説明するように、CORSアプローチを採用してS3に直接アップロードすることを検討してください: StreamそのユーザーはAmazonに直接アップロードしますs