LoginSignup
18

More than 5 years have passed since last update.

AWS_SDKでS3にアップした画像を開くとブラウザに表示されないあなたへ

Last updated at Posted at 2016-06-17

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にアクセスすると、ブラウザに画像が表示されるわけでなく…

スクリーンショット 2016-06-17 15.12.04.png

こんな感じでブラウザがダウンロード開始しちゃう。
違うんだよ!保存じゃなくてブラウザに表示さえしてくれればいいんだよ!という気持ちになる。
Qiitaの画像なんかは同じくs3の画像だけど、開くとブラウザに表示される。
何が違うんだ!

Content-Typeを指定してなかった

AWSのマネジメントコンソールで手作業でアップした画像ファイルはブラウザで表示できた。
aws-sdkから上げたファイルとオブジェクトのプロパティ見比べてみるとここが違った

  • 手作業で上げたjpegファイル

スクリーンショット 2016-06-17 15.26.37.png

  • aws-sdkで上げたjpegファイル

スクリーンショット 2016-06-17 15.30.44.png

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のパッケージを使って取れるものです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18