0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

webページから署名付きリンクでs3バケットへのアップロードする方法

Last updated at Posted at 2025-10-03

はじめに

作成したアプリの「呼出元でファイル添付ができない」が、「s3バケットに保持して利用させたい」とのことで、以下の仕組みを作成したことのメモ。

  • s3バケットへの署名付きURLでアップロード
  • cloudFrontでWebアップロードページの公開
    • ※ httpリクエストのputが必要/リンククリックでは不可なため

構成

  • s3/upload
    • ファイルをアップロードするバケット
    • プログラムでは、このバケットへの署名付きURLを作成する
  • cloudFront
    • 公開用URLを生成
    • 「s3のアップロードページ」にリダイレクトさせる
  • s3/contents
    • 「index.html(WEBアップロードページ)」を保持するバケット
    • cloudFrontのオリジンになる

しくみ

  • http://******.cloudfront.net?s3_url=s3://upload/hoge.fuga URLを作成
    • http://******.cloudfront.net
      • cloudFrontのデフォルトURL
      • s3/contentのindex.html(公開用URLのアップロードページ)にリダイレクトする
    • ?s3_url=s3://upload/hoge.fuga
      • 署名付きURLをパラメータとして保持
      • 「公開用URLのアップロードページ」表示時に保持し、送信時に利用する

AWSサービスの設定内容/注意点

s3/upload

バケットポリシー

  • 対象のroleに "s3:PutObject" が付与されていること
    image.png

Cross-Origin Resource Sharing (CORS)

  • cloudFrontからのPUTが許可されていること
    image.png

s3/contents

バケットポリシー

  • cloudFrontからのgetが許可されていること
    image.png

CORS は設定不要

cloudFront

一般

  • ディストリビューションドメイン名:公開用のリンク
  • デフォルトルートオブジェクト:index.html を対象ページとする
    image.png

オリジン

  • s3バケット のpathを設定することで、対象階層のindex.html(一般で指定)にリダイレクトされる
    image.png

  • Origin access control:Sをオリジンと設定(サイドメニューからも確認/編集可能)
    image.png

ビヘイビア

  • リダイレクト対象とする
    image.png

index.html(公開用URLのアップロードページ)

  • s3/contentsに配置したファイル

  • {s3バケット のpath} / {cloudFronf.一般.デフォルトルートオブジェクト} に配置されていること
    image.png

  • リクエストでの送信が必要

const binaryData                     // <- ページに渡したファイルのバイナリデータ
const xhr = new XMLHttpRequest();
xhr.open('PUT', presignedUrl, true); // <- 署名付きURLへのPUTをリクエスト送信対象とする
xhr.setRequestHeader('Content-Type', file.type || 'application/octet-stream');
xhr.send(binaryData);                 //  <-アップロードページで保持したファイルを送信

実装(python)

  • generate_presigned_url にて署名付きURLを作成できる
config = Config(signature_version='s3v4', 
    s3={'addressing_style': 'virtual'}  # <- 仮想ホスト形式を強制
)
s3_client = boto3.client("s3", config=config)
url = s3_client.generate_presigned_url(
    "put_object",
    Params={"Bucket": bucket,  # <- バケット名
    "Key": key },              # <- バケット内の階層(putなのでファイルまで指定)
    ExpiresIn=expire_seconds, # <- 署名付きURLの失効期限/秒
    HttpMethod='PUT'           # <- HTTPメソッドを明示
)

注意点

署名付きURLに「エンコード/デコード」が必要

署名付きURLはトークンや暗号化情報を保持する。
パラメータの欠落を防止するため「プログラムでエンコード/webページでデコード」が必要

  • エンコード (python)
    base64.urlsafe_b64encode(presigned_s3_upload_url.encode()).decode()

  • デコード (html)
    atob(encodedUrl.replace(/-/g, '+').replace(/_/g, '/'));

cloudFrontのキャッシュ削除

cloudFront は「オリジンを公開」している。
そのため、s3のindex.htmlを変更した時にキャッシュ削除が必要

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?