BLOG

【vue.js】AWS-S3へ簡単にファイルをアップロードする方法

2019.11.20
TECH

こんにちは、タロウです。

vueで作成したアプリケーションをAWSで稼働させる機会があり、
今後使う機会が増えそうなので書き残します!

S3にファイルをアップロードする際、大きく2つの方法で迷います。

  • クライアントサイドから直接S3にアップロードさせる
  • クライアントサイドからサーバAPIを経由してS3にアップロード

どっちで実装しよう。。

クライアントサイドから直接S3にアップロードさせる

クライアント側にS3のアクセスキーを持たなければいけないためセキュリティリスクが高いです。
それも承知の上・・であれば、期限付きURLを発行して直接アップロードさせる方法が良いです。

クライアントサイドからサーバAPIを経由してS3にアップロード

今回はこちらの方法を書き留めます。(これを実装すれば直接アップロードも機能を削るだけで出来ます)
クライアントサイド、サーバAPIのS3の連携部分と分けて解説します!

完成形


ぼく、水彩画の線結構好き。

もくじ

  • バケットの準備
  • プラグインを入れよう
  • クライアントサイド
  • サーバサイドAPI

バケットの準備

AWSコンソールにログインしてS3の設定画面からバケットを作成します。

バケット名とリージョンを設定して、あとはデフォルトのまま進めます。
(パブリックアクセスはOFFにしておきます)

プラグインを入れよう

AWSでnodejs用のプラグインが準備されているので、インストールします。

npm install --save aws-sdk fs

AWSを操作するためのライブラリと、
nodejsでファイル操作を行うためのライブラリをインストールします。

クライアントサイド

最低限のファイル選択と、ボタンを配置してます。
methods内の処理がポイントです!

<template>
    <div id="app" class="family">
		ファイルを選択
        <input @change="changeFile" ref="rfafile" type="file" />
        <input @click="regist" type="button" value="Upload"/>
    </div>
</template>
<script>
import axios from 'axios';
export default {
  data() {
    return {
      uploadfile: {},
    };
  },
  methods: {
    changeFile(e) {
      const files = e.target.files || e.dataTransfer.files;
	  // ファイルが選択されたら変数に入れる
      this.uploadfile = files[0];
    },
    // 送信アクション
    async regist() {
      // パラメータ生成
      var params = new FormData();
      // FormDataにアップロードするファイルを設定
      params.append('file', this.uploadfile);
      // API実行
      let { data } = await axios.post(
        '/' + process.env.API_PATH + '/hoge/fileUpload',
        params,
        {
          headers: {
            // multipartで送信
            'content-type': 'multipart/form-data',
          },
        }
      );
    },
  },
};
</script>
<style>
</style>

axiosでExpressjsで作成したAPIを呼ぶようにしてます。

サーバサイド

Vueから受けとったファイルをS3にアップロードする処理を実装します。
npmでインストールしたaws-sdkを使用するとすごく簡単です。

var AWS = require('aws-sdk');
var bodyParser = require('body-parser');
var multer = require('multer');
// アップロードされたファイルの一時格納フォルダ
var upload = multer({ dest: '/tmp/express/uploads/' });
var fs = require('fs');

// AWSのアクセスキーをjsonで記載
AWS.config.loadFromPath('config/aws-credentials.json');
// リージョンを指定
AWS.config.update({ region: 'ap-northeast-1' });

module.exports = function(app) {
  // API設定
  var path = '/aws';
  // POSTパラメータの受取
  app.use(bodyParser.urlencoded({ extended: false }));
  app.use(bodyParser.json());
  // アップロードAPI
  app.post(path + '/fileUpload', upload.single('file'), async function(
    req,
    res
  ) {
    // S3のインスタンスを生成
    var s3 = new AWS.S3();
    // アップロード用のパラメータを設定
    var params = {
      // バケット名
      Bucket: 'test',
      // アップロード後のファイル名(hogehoge/uploadfile.png などのディレクトリ指定も可)
      Key: req.file.originalname,
    };
    // fsで一時ディレクトリにアップロードされたファイルを読み込み
    var v = fs.readFileSync(req.file.path, (err, data) => {
      return data;
    });
    // パラメータに設定
    params.Body = v;
    // ファイルアップロード処理実行
    s3.putObject(params, function(err, data) {
      if (err) {
        console.log(err, err.message);
      } else {
        console.log("アップロード成功!");
      }
    });
  });
};

実装は以上になります!
画面からファイルを選択しアップロードするとS3にファイルがアップロードされているはずです!

余談:

S3にアップロードしたファイルを期限付きURLを発行して参照する方法も紹介します。

// 期限付きURL取得(900:15分)
// パラメータを設定
var getUrlparams = {
	// バケット名
	Bucket: 'test',
	// S3に格納済みのファイル名
	Key: "hoge.png",
	// 期限(秒数)
	Expires: 900,
};
// URL発行
s3.getSignedUrl('getObject', getUrlparams, function(err, url) {
	console.log('期限付きURL:', url);
});

グローバルにしたくない・・けど、ユーザーにS3から直接ダウンロードさせたい・・時などに使えます!
昔にPHPでも実装したので、PHP版はこちらをご参照ください!

まとめ

S3へのアクセスでよく使いそうなロジックを実装してみました!
ほかにもファイル一覧を返却したり、削除したりと一通りの操作が簡単に実装できます。
AWSを使っている現場にはメジャーなプラグインかもしれませんが、ご紹介でした!

The following two tabs change content below.
Taro

Taro

ディレクターも、サーバ構築も、ゴリゴリ開発もやります。 オールマイティ担当。 スパイスも甘いものも大好き。