Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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

kashitaka1118
マスコミの端くれでインフラとアプリの間をいったりきたりするエンジニア。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした