Ruby
S3

クライアントから S3 に直接アップロードする方法

streampack の Tana です。

動画を管理するCMSは、様々な拡張子のファイルや数GB動画を同時に

アップロードされることもあるので、サーバー経由の場合だと下記の考慮をする必要があります。


  • メモリ消費

  • ディスクサイズ

  • タイムアウト

  • プロセス処理時間 (他のリクエストが待たされる・受け付けなくなる)

今回、外部サイトとのアップロード連携する必要がありそうで、

サーバーの負荷を考慮したくないので(今もしていない)、

pre-sigined URL(PUT)版で s3 に直接アップロードする方法の一つです。

下記はサーバ経由アップロードとS3直接アップロードの違い:

D149F043-F749-4551-8E52-5531D96745A5.png

参照元

Signature V4 を自前で作成するのは複雑なので、

今回は AWS Ruby SDKを使って、pre-Signed URL を生成して、アップロードします。

> obj = s3.bucket('your-bucket-name').object('tmp/test.mp4')

> url = URI.parse(obj.presigned_url(:put))
>
> puts url
> https://your-bucket-name.s3.ap-northeast-1.amazonaws.com/tmp/test.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIxxxxxxxxxxxxxxx%2F20190117%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20190117T103740Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=3e6d8de19dca1079f43468a9b03d2a06b80a98f9dee7399431xxxxxxxxx


tmp/test.mp4 は s3 の出力先

PUT Methodでファイル名を指定して投げるだけで s3 にアップできます。


$ curl -X PUT \

'https://your-bucket-name.s3.ap-northeast-1.amazonaws.com/tmp/test.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIxxxxxxxxxxxxxxx%2F20190117%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20190117T103740Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=3e6d8de19dca1079f43468a9b03d2a06b80a98f9dee7399431xxxxxxxxx' \
-F file=@/Users/demo/Desktop/orig.mp4

簡単ですね。

PUT 方式だと、最大5GBまでなので、もしそれ以上のファイルをあげる場合は、Multipart Upload を使う必要がより複雑です。

これらを決められたパスのURLを発行するAPIを渡す仕組みを提供し、アップロードしてもらえれば、

あとはこちらで Lambda でそのファイルを適切な場所に移動したり変換したり自由にできます。

以上、小ネタでした。