AWS S3 に対応した!
昨日、Google Photos の画像の直接貼り付けがうまくいっていない という話をした。あのあともう一度 Google Photos の画像の URL を直接取得して貼り付けてみたが、どうもうまくいかない。今試しにもう一度やってみたらうまくいったんだけど、明日になったらまた URL が変わってアクセスできなくなっているかもしれない。
というわけで、前々から実装しようと思っていてなかなか実装できていなかった AWS S3 対応を、ようやく重い腰を上げて実行することにした。
アプリケーションサーバ (Rails) 側に一旦画像をアップロードして、アプリケーションサーバから S3 にアップロードする、みたいな実装になるかなあと思っていたんだけど、S3 はアプリケーションサーバを経由せずに、ブラウザから直接アップロードすることができるということを知った。
- ブラウザからS3へのダイレクトアップロード
- 【presigned url】サーバーを経由せずにS3に画像・動画などのファイルをアップロードする
- S3に直接画像をアップロードする(Ruby on Rails)
今回主に参考にしたのは 1 つめの記事だ。
ブラウザから直接 S3 にアップロードすることのメリットとしては、アプリケーションサーバを介さないので、その分速く画像をアップロードできるという点や、画像のサイズを気にしなくて良い (あまり大きすぎるとアプリケーションサーバの Nginx で弾かれたりもする) という点があげられる。
その代わり、アプリケーションサーバでのバリデーション (それこそファイルサイズが大きすぎる場合は弾くとか) や、画像を加工したり (解像度を下げたりメタデータを削除したり) することができなくなってしまう。あとモデルの関連付けもできない。
今回は、特にサーバで処理することもなくそのまま画像をアップロードすれば良いということ、アップロードするのは自分しかいないこと、それからモデルと関連付ける必要もなく、バリデーションとかセキュリティ関連のこともあまり気にしなくても良いということで、ブラウザから直接アップロードする実装にした。
今日は朝の 4 時半くらいに起きて、現在 (21 時半) までずっと実装をしていた。まず S3 の設定とかで少しだけ手こずった。前に Mastodon で同じことをしたんだけどすっかりやり方を忘れていた。前に見た記事を参考にしながら日記用のバケットの設定やら CloudFront の設定やらなんやらした。
S3 のシークレットキーの設定やアプリケーションサーバ側の処理自体はそんなに難しくはなかったが、ブラウザ (クライアント) 側の実装にめちゃくちゃ手こずってしまった。
あんまり JavaScript 得意じゃないというのと HTTP リクエスト周りのサンプルコードが理解できなかったこともあって、結構大変だった。
サンプルコードでアップロードするところまででも時間がかかったが、さらにそこから複数アップロードとか、進捗表示 (というかアップロードしようとしている画像の枚数とアップロード完了した画像の枚数の表示) とか、アップロード前にページを離れようとしたときに警告を出すなどの実装で結構時間がかかってしまった。
特に複数アップロードが異状に大変だった。ただループ回せば良いだけかと思っていたら全然うまくいかなくて大変だった。
でもなんとか最低限のことはできるようになったので良かった。
ただ現状だとアップロードした画像がエディタページでは表示されないのが不便。Qiita みたいに画面左が編集フォームで、画面右がマークダウンをパースした表示とかにすれば良いんだけど、それを実装するにはまた時間がかかりそう。
あと現時点では画像アップロードボタンを押す方式しかないので、いずれはドラッグアンドドロップにも対応したい。というか以前は (S3 じゃなくてアプリケーションサーバに直接画像をアップロードするときは) ドラッグアンドドロップもできていたので、逆に退化してしまっている。
といっても、以前も画面下にある枠にしかドラッグアンドドロップできなくて、ページ最下部までスクロールしないと画像がアップロードできなかったから使い勝手は悪かった。S3 版はドラッグアンドドロップはまだ未対応なものの、画像がアップロードボタンが追従する位置にいるのでむしろ UX は改善したんじゃないかと思う。
文字を入力するフォームに直接ドラッグアンドドロップできるようにして、その画像が画面右のパースしたほうに表示されるようになればだいぶ使いやすくなるだろう。
ちなみにブラウザからアップロードする場合は、アップロードが完了する前から画像の URL が取得できる。つまり ![IMG_7596.jpg](https://diary.noraworld.media/images/2020/10/72cb2c1e46b974d9eb427483e1f0ae584f4d1850f0bb666903cd0010882028d0.jpg)
のようなものが画像アップロード前に挿入できるというわけだ。
これは便利1である反面、まだ画像がアップロードされていない状態でページを離れようとする (日記を更新するボタンを押してページ繊維するのも同様) と画像がアップロードされずに中断されてしまうので、そうならないように、現在、何枚の画像がアップロード中で、何枚がアップロード完了したのかを表示するようにした。
そして、アップロード中の画像がある場合はページ遷移前に警告が出るようにした。以前から、編集中にページを離れようとすると警告が出るようになっていたのだが、画像アップロード中にも出るようにした。
今後改良の余地はあるが、今のところはこれで問題なさそうだ。
【おまけ】前回届いた ScanSnap iX 1500 の画像をテストで貼ってみる。S3 からこんにちは〜。
今日は明け方から夜までずっと実装していたので疲れた。もう今日は休もう。今日はがんばった。
江東区からラジオが届いた
夕方過ぎくらいに突然ヤマトから荷物が来た。Amazon で何も頼んだ覚えないのになと思っていたら、江東区からラジオが届いた。
うーん、シンプルにいらない……。
eGPU コスパ最悪だし微妙すぎる
なんか今日は、eGPU の不具合が多かった。ケーブル抜いてないのに、eGPU が不正に取り外されましたとかってなって画面がおかしくなって接続し直さなきゃならないことが 2 回もあった。
やっぱ eGPU は微妙すぎるな。抜くときにいちいち使用中のアプリケーションを終了させないといけないし、ケーブル抜いてないのに不正な取り出しとかになることがあるし、eGPU だけで場所取るし、パフォーマンスも 20 〜 30 % 落ちるし、値段は圧倒的に高いし、MacBook なのに取り外しが面倒なせいで移動できないし……。
自作 PC を作ったら eGPU は卒業しても良いかもな……。開発や作業メインは自作 PC を作っても Mac になるだろうけど、開発とか作業では eGPU が必要なくらいのことはやらないだろうし。
-
アップロード完了して画像のマークダウン (
![]()
) が挿入されるまで文章の入力を待つ必要がないからね。async の恩恵を享受できる。S3 のリージョンはバージニア北部にしているので日本から画像をアップロードしようとすると数秒待たされる。AWS を使い始めたときは、とりあえずリージョンもスタンダードにしたいと思っていたのでバージニア北部を選んだが、やっぱりパフォーマンスとか考えると東京にしたほうが良かったかなとも思う。でも気軽にリージョンを変更することもできないし、ここの決断はなかなか難しいところである。 ↩