Nuxt + Uppy で S3 に画像をアップロードする

Uppy 使ってみた

今のプロジェクトでは Nuxt.js を用いて開発を行っているため、Nuxt 絡みでGWになにか作りたいなと思っていました。

そこで、見つけた Uppy ( https://uppy.io/ ).

このブログで使っている画像を毎度 CyberDuck でアップロードして、URLをコピペして。。みたいなことをしていて、若干のツラミがあったため、今回は Uppy を使って S3 へ画像をアップロードするツールを作ってみました。

その過程で、いくつかUppy 特有の使い勝手みたいなところがあったので、本記事でご紹介します。

大まかなしくみ

この Uppy はフロントエンド側で Uppy のライブラリを用いて UIを作っていく部分と、Companion と呼ばれる画像を実際にアップロードするバックエンド処理に分かれています。

今現在の Uppy 使ってみた系の記事では、フロントエンド側の実装が語られる一方で、バックエンド側は XHRをベースにした画像アップロードをしているものしか見かけず、実際にS3に画像をアップロードしようとすると、少し苦しむ部分があるかもしれません。

今回は、S3に実際にアップロードできるところまで、本記事で紹介していきます。

クライアント(Nuxt)側について

Nuxtのプロジェクトは用意できている前提で進めてしまいますが、まず以下のパッケージを追加します。

$ yarn add @uppy/core @uppy/dashboard @uppy/aws-s3

その上で、ざっくりと vue ファイルを作っていきます。 テンプレート部分はこんな感じ。特に変わったことはしていないです。

<template>
  <section class="section">
    <div class="columns is-mobile">
      <b-button id="select-files">Upload new image</b-button>
    </div>
  </section>
</template>

そして、js 部分は以下。

import Uppy from '@uppy/core'
import Dashboard from '@uppy/dashboard'
import AwsS3 from '@uppy/aws-s3'

export default {
  data() {
    return {
      uppyId: 'uppy-trigger'
    }
  },
  mounted() {
    const uppy = Uppy({
      allowMultipleUploads: true,
      restrictions: {
        allowedFileTypes: ['image/*']
      }
    })
      .use(Dashboard, {
        trigger: '#select-files'
      })
      .use(AwsS3, {
        companionUrl: process.env.COMPANION_URL
      })
  }
}

フロント側はこれだけで S3 にアップロードする準備ができてしまいます。 超簡単でビビります。

バックエンド(Uppy/Companion)について

フロント側のコードを用意していて、少し謎なのが companionUrl なのですが Uppy では Companion について、以下のようなドキュメントがあります。

https://uppy.io/docs/companion/

めちゃくちゃざっくり意訳をすると、ユーザーが様々なリソース(Instagram, Dropbox…) からファイルを選択し、それをさらなるリソース(Dropbox, S3, OneDrive…) にバイパスさせるための仕組みのようです。

これがなぜ必要になってくるかというと、上記フロント側のコードを見てもわかるように S3 に画像をアップロードするにあたり、クレデンシャル情報は一切書きませんし、フロント側で出力するわけにも行きません。

そこで、このコンパニオンにクレデンシャル情報をもたせ、リソースのアップロードをバイパスさせることで、様々なリソースへのアップロードを可能にするようです。

ということで、このコンパニオンを用意していきます。

heroku にコンパニオンを用意する

https://github.com/transloadit/uppy/tree/master/packages/%40uppy/companion#deploy-to-heroku

とても丁寧にメンテされているドキュメントがありますので、こちらを参考にしてください。

まずは README に書かれているる通り、heroku にアプリケーションをデプロイします。

別段 heroku でなくとも node.js が動く軽量なサーバーをすぐに用意できそうであれば、そちらでもいいかもです。

その後、このアプリケーションに対し、クレデンシャル情報をセットしていきます。

クレデンシャルをセットしていく

https://uppy.io/docs/companion/#Configure-Standalone

こちらに設定可能なクレデンシャルのキーが書かれているので必要に応じて設定していきます。 今回、S3に画像をアップロードしていくにあたっては以下の情報で十分です。

  • COMPANION_AWS_ACL
  • COMPANION_AWS_BUCKET
  • COMPANION_AWS_EXPIRES
  • COMPANION_AWS_KEY
  • COMPANION_AWS_REGION
  • COMPANION_AWS_SECRET
  • COMPANION_AWS_USE_ACCELERATE_ENDPOINT
  • COMPANION_DATADIR
    • 特に何もディレクトリを切ってないので . で設定
  • COMPANION_DOMAIN
    • heroku でデプロイしたドメインを設定
  • COMPANION_SECRET
    • ランダムな文字列を決め、セットしてあげればOK

ドキュメントにも一応各キーの説明が書かれてるんですが、文脈が不足しており、意味わからんwというものも多かったです。(解釈が違う。というときには教えて下さい 🙏

S3バケット に CORS の設定をする

あとは、フロント側のURLを CORSで許可するようにします。

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>https://xxxxx.herokuapp.com</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>Authorization</AllowedHeader>
    <AllowedHeader>x-amz-date</AllowedHeader>
    <AllowedHeader>x-amz-content-sha256</AllowedHeader>
    <AllowedHeader>content-type</AllowedHeader>
</CORSRule>
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
</CORSRule>
</CORSConfiguration>

こんな感じで指定してあげれば、フロント側からアップロードできるようになっているかと思います。

まとめ

Uppy を見つけたときは、めちゃくちゃお手軽そうに見えたのですが、いざ使ってみようとすると準備物が多く、なかなか手間取りましたw

特に Companion の考え方を理解するまでに時間がかかってしまった。。 一方でここまで組み込めれば、S3 だけじゃなく他のサービスへのアップロードも簡単に行えたり、アップロードの対象に WebCamera を加えたり、外部URLを加えたり。というのも簡単にできるようになるので、初期投資としてはありだったのかもしれません。

個人的には、画像をリサイズしたり、軽くしたりということもやっていきたいので、ちょいちょいいじっていきたいと思います。

Related Posts