フルスタックエンジニアのQuang Tranです。エンジニアとして4年間働くなかで、Amazon S3のようなクラウドストレージへのファイルアップロードには何度も苦労してきました。以前は、クライアントから受け取ったファイルをいったんサーバーに保存し、そこからS3に送る従来の方法を使っていました。一見シンプルな処理ですが、すぐにサーバーのリソースを圧迫するようになり、サーバーは過負荷で「悲鳴」を上げるようになりました。
そんなときに出会ったのが、サーバーに負荷をかけずにクライアントからS3へ直接ファイルをアップロードできる署名付きURL(Presigned URL)です。本記事では、署名付きURLの仕組みと実装方法をご紹介します。
従来のファイルアップロード
SNSに写真を投稿するなど、ファイルアップロード機能のあるアプリケーションでは、端末から写真を選択してサーバーに送信し、保存するという流れになります。従来のアップロード方式の手順は次のとおりです。
- ユーザーが端末から写真を選択する
- クライアントがサーバーに写真のアップロードをリクエストする
- サーバーが写真を受け取って処理し、ストレージに保存する

従来のファイルアップロードの流れ
この流れはシンプルに見えますが、サーバーのパフォーマンスに影響を及ぼす可能性があります。数千人のユーザーが同時に大量のデータをアップロードすれば、サーバーは過負荷に陥りかねません。そのため、アプリケーションサーバーをスケールさせ、十分なネットワーク帯域を確保する必要が出てきます。
こうした課題への解決策としてAWSが提供しているのが、署名付きURLの機能です。では、署名付きURLとは何でしょうか。
署名付きURL(Presigned URL)とは
署名付きURLとは、特定のS3オブジェクトへの一時的なアクセス権をユーザーに付与するためのURLです。署名付きURLを使えば、サーバーを経由せずにS3のオブジェクトを直接読み取ったり、アップロードしたりできます。相手側にAWSのセキュリティ認証情報や権限がなくてもアップロードが可能です。なお、署名付きURLで指定したバケットに同じキーのオブジェクトがすでに存在する場合、Amazon S3は既存のオブジェクトをアップロードされたオブジェクトで置き換えます。
署名付きURLを作成する際には、次の情報を指定する必要があります。
- Amazon S3のバケット名
- オブジェクトキー(読み取りの場合はバケット内のオブジェクト、アップロードの場合はアップロードするファイル名)
- HTTPメソッド(オブジェクトの読み取りはGET、アップロードはPUT)
- 有効期限
- AWS認証情報(アクセスキーID、シークレットアクセスキー)
署名付きURLは、有効期限が切れるまで何度でも使用できます。
Amazon S3は署名付きURLを通じてオブジェクトへのアクセスを許可します。署名付きURLを生成できるのは、バケットの所有者または有効なセキュリティ認証情報を持つユーザーに限られます。
署名付きURLを使ってS3にファイルをアップロードする流れは、次の図のとおりです。

署名付きURLを使ったファイルアップロードの流れ
アップロード用の署名付きURLを作成する方法
署名付きURLの概要がわかったところで、実際に作成して写真をアップロードする方法を見ていきましょう。
アップロード用の署名付きURLを作成する方法は、次の2つです。
- AWS Toolkit for Visual Studio(Windows)を使う
- AWS SDKを使って、ファイルアップロード用のPUT署名付きURLを生成する
本記事では、AWS SDK for JavaScriptを使ってPUT署名付きURLを生成する方法を紹介します。
AWS SDK for JavaScriptを使う
まず、S3オブジェクトの読み書き権限を持つアカウントでAWSマネジメントコンソールにログインします。
- AWS SDKで署名付きURLを生成する場合、有効期限は作成から最長7日間です。
- アップロードの前に、AWS認証情報(アクセスキーID、シークレットアクセスキー)、リージョン、S3バケット名、オブジェクトキーを準備し、サーバー側で安全に管理しておく必要があります。
署名付きURLの作成を始める前に、次の重要なポイントを押さえておきましょう。
- S3バケットへのパブリックアクセスをすべてブロックする(データセキュリティの基本であり、意図しない情報漏えいや機密情報への不正アクセスを防ぎます)
- AWS認証情報(アクセスキーID、シークレットアクセスキー)をフロントエンドのコードに絶対に保存しない
- 環境変数やシークレット管理サービスを使って、AWS認証情報を安全に保管する
- IAMの権限を必要最小限に絞る(AWSが推奨する最小権限の原則)
- CORSを設定し、他のオリジンからのファイルアップロードリクエストを許可する
S3へ画像を直接アップロードする仕組みは、次の手順で構築します。
- フロントエンドから、バックエンドサーバーの署名付きURL生成APIを呼び出し、保存したいオブジェクトキーを送信します。
- バックエンドでは、次のように署名付きURLを生成するAPIを作成し、フロントエンドに返します。
1import {2 PutObjectCommand,3 S3Client,4} from '@aws-sdk/client-s3';5import { getSignedUrl } from '@aws-sdk/s3-request-presigner';67const createPresignedUrlWithClient = async ({ region, bucket, key }) => {8 const client = new S3Client({9 region,10 credentials: {11 accessKeyId: 'your access key id',12 secretAccessKey: 'your secret key id',13 },14 });15 const command = new PutObjectCommand({ Bucket: bucket, Key: key });16 return await getSignedUrl(client, command, { expiresIn: 36000 });17};1819const presignedUrl = await createPresignedUrlWithClient({20 region: 'ap-southeast-1',21 bucket: 'your-bucket-name',22 key: 'example.txt',23});
上記のコードは説明用に認証情報を直接記述していますが、実際の運用では環境変数やAWS Secrets Managerなどから読み込み、コードに認証情報を書かないようにしてください。
- フロントエンドはレスポンスを受け取り、PUTリクエストでS3バケットにファイルを直接アップロードします。
1const putToPresignedUrl = (presignedUrl) => {2 const data = 'Hello World!';3 axios.put(presignedUrl, data);4};

アップロード後にS3に保存されたオブジェクト

オブジェクトの内容
署名付きURLの例:
1https://presignedurldemo.s3.ap-southeast-1.amazonaws.com/example.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAUPMYNICO4HMDKONH%2F20250101%2Fap-southeast-1%2Fs3%2Faws4_request&X-Amz-Date=20250101T021742Z&X-Amz-Expires=36000&X-Amz-Signature=9f29f0f34a19c9e9748eb2fc197138d4345e0124746f99ad56e27e08886fa01a&X-Amz-SignedHeaders=host&x-amz-checksum-crc32=AAAAAA%3D%3D&x-amz-sdk-checksum-algorithm=CRC32&x-id=PutObject
S3は、URLに含まれるクエリパラメータをもとに、アップロード操作を許可するかどうかを判断します。主なパラメータは次のとおりです。
- X-Amz-Algorithm:使用する署名アルゴリズム。通常はAWS4-HMAC-SHA256です。
- X-Amz-Credential:アクセスキーIDとリクエストのスコープを含む文字列。形式は
<AccessKey>/<Date>/<Region>/s3/aws4_requestで、リクエストの署名に使われた認証情報をAWSが識別するために使われます。 - X-Amz-Date:URLが生成された日時(UTC)。形式は
YYYYMMDD'T'HHMMSS'Z'です。 - X-Amz-Expires:URLの有効期限までの秒数(例:1時間なら3600)。この時間を過ぎるとURLは無効になります。
- X-Amz-SignedHeaders:署名に含まれるヘッダーの一覧。通常はhostのみですが、署名時に指定すればcontent-typeなども含められます。
- X-Amz-Signature:実際の暗号署名。リクエストが改ざんされていないことを保証し、送信者が有効な認証情報を持っていることを証明します。
署名付きURLの生成方法がわかったところで、利用時に考慮すべき制約も確認しておきましょう。
S3署名付きURLの制約
- アップロード上限は5GB:S3では1回のリクエストでアップロードできるサイズが5GBまでに制限されており、簡単に引き上げる方法はありません。
- URL管理の手間:アップロードのたびに固有のURLを生成する必要があるため、コードやバックエンドのロジックが複雑になります。
- 意図しないアクセスのリスク:URLを知っていれば誰でも、有効期限が切れるまでアップロードできてしまいます。ユーザーを検証する仕組みは組み込まれていません。
- クライアント側アップロードの課題:アップロードの途中でエラーが発生すると、データの不整合が生じる可能性があります。
あわせて読みたい:
- AWS Lambdaを使いこなす:サーバーレスコンピューティング入門(英語)
- AWS Lambdaのトリガーとイベント:S3・DynamoDB StreamsでLambda関数を動かす方法
- 信頼性の高いAWS Lambda関数を構築するためのベストプラクティス
まとめ
本記事では、S3バケットを公開することなく、S3へオブジェクトを直接アップロードする方法を紹介しました。署名付きURLを使えばサーバーの負荷を抑えられる一方、5GBのアップロード上限やURL管理の手間といった制約もあります。ユースケースに合わせて最適な方法を選んでください。
参考資料:
- Uploading objects – Amazon Simple Storage Service(AWS)
- Uploading objects with presigned URLs – Amazon Simple Storage Service(AWS)
出典:Uploading objects to AWS S3 with presigned URLs(SupremeTech、著者:Quang Tran)。日本語に翻訳して掲載しています。




