Node.jsから画像のアップ
という機能作った時にハマった話
コードはこんな感じ
var
AWS = require('aws-sdk'),
fs = require('fs'),
upload;
AWS.config.update({
accessKeyId: 'AKIXXXXXXXXXXXXX',
secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXX',
region: 'ap-northeast-1'
});
upload = function ( file, callback ) {
var
bucketName = "hogehogeBucket",
fileName = file.filename,
body = fs.readFileSync(file.path),
s3 = new AWS.S3({params: {Bucket: bucketName, Key: fileName}});
s3.upload({Body: body}, function(evt) {
// console.log(evt);
}).send(function(err, data) {
// 結果返す
callback(err, data);
});
};
module.exports = {
upload : upload
};
画像はアップできるんだけど、アップしたファイルのURLにアクセスすると、ブラウザに画像が表示されるわけでなく…
こんな感じでブラウザがダウンロード開始しちゃう。
**違うんだよ!保存じゃなくてブラウザに表示さえしてくれればいいんだよ!**という気持ちになる。
Qiitaの画像なんかは同じくs3の画像だけど、開くとブラウザに表示される。
何が違うんだ!
Content-Typeを指定してなかった
AWSのマネジメントコンソールで手作業でアップした画像ファイルはブラウザで表示できた。
aws-sdkから上げたファイルとオブジェクトのプロパティ見比べてみるとここが違った
- 手作業で上げたjpegファイル
- aws-sdkで上げたjpegファイル
Content-Typeがoctet-streamになっとる。content-typeを指定するパラメータが抜けてたのね。
これでOK
s3.upload関数の引数にContentTypeパラメータを指定してやる
var
AWS = require('aws-sdk'),
fs = require('fs'),
upload;
AWS.config.update({
accessKeyId: 'AKIXXXXXXXXXXXXX',
secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXX',
region: 'ap-northeast-1'
});
upload = function ( file, callback ) {
var
bucketName = "hogehogeBucket",
fileName = file.filename,
body = fs.readFileSync(file.path),
s3 = new AWS.S3({params: {Bucket: bucketName, Key: fileName}});
// ★ ↓この部分 ★
s3.upload({Body: body, ContentType: file.mimetype}, function(evt) {
// console.log(evt);
}).send(function(err, data) {
// 結果返す
callback(err, data);
});
};
module.exports = {
upload : upload
};
情報探しても意外と出てこなかったけどこれって常識?探し方が悪かったのかなあ
ちなみに
上の関数を他から呼び出すなら
var s3 = require( './lib/s3' );
s3.upload( req.file, function (err, data) {
// なんか処理
}
的な感じで使えます。(上記のモジュールはlib/s3.jsとして保存)
引数のreq.fileはmulterと言うExpressのパッケージを使って取れるものです。