ダイレクトアップロードを使用すると、クライアントからObject Storage Service (OSS) にデータを直接アップロードできます。 ダイレクトアップロードソリューションは、アプリケーションサーバーとの間でオブジェクトを転送する必要をなくすことにより、アップロードを高速化し、アプリケーションサーバーのリソース使用量を削減します。 このトピックでは、このソリューションの利点、実装方法、およびベストプラクティスについて説明します。
メリット
従来のサーバーおよびクライアントアーキテクチャでは、アプリケーションサーバーからOSSにデータをアップロードするのが一般的なアップロード方法です。 クライアントはオブジェクトをアプリケーションサーバーにアップロードし、アプリケーションサーバーはオブジェクトをOSSにアップロードします。 アップロードプロセス中、データはネットワーク経由で2回転送する必要があります。 これは、ネットワークリソースの浪費及びアプリケーションサーバのリソース使用の増加をもたらす。 この問題を解決するには、オブジェクトをアプリケーションサーバーにアップロードせずに、オブジェクトをOSSに直接アップロードします。
実装方法
クライアントからOSSに直接データをアップロードするには、次の問題を解決する必要があります。
CORS
クライアントがwebクライアントまたはミニプログラムの場合、クロスオリジンリソース共有 (CORS) を許可する必要があります。 データのセキュリティを確保するために、ブラウザとミニプログラムは通常CORSを禁止します。 これにより、クライアントコードを使用してOSSに接続できなくなります。 OSSバケットのCORSルールを設定して、webクライアントまたはミニプログラムのドメイン名がOSSにアクセスできるようにすることができます。 CORSルールの設定方法の詳細については、「CORS」をご参照ください。
セキュリティ権限付与
オブジェクトをOSSにアップロードするには、RAMユーザーのAccessKeyペアを使用して署名認証を完了する必要があります。 クライアントが永続的なAccessKeyペアを使用している場合、AccessKeyペアが漏洩する可能性があります。 これは、セキュリティリスクを引き起こす可能性があります。 この問題を解決するには、次のいずれかのソリューションを使用して安全なアップロードを実装します。
アプリケーションサーバーのSTSから一時的なアクセス資格情報を取得
ほとんどのオブジェクトアップロードのシナリオでは、Security Token Service (STS) SDKを使用してアプリケーションサーバーの一時的なアクセス資格情報を取得し、一時的なアクセス資格情報とOSS SDKを使用してクライアントからOSSに直接オブジェクトをアップロードすることを推奨します。 クライアントは、アプリケーションサーバ上の一時的なアクセス資格情報を再利用して署名を生成することができる。 これは、マルチパートアップロードと再開可能アップロードを使用してラージオブジェクトをアップロードするシナリオに適しています。 ただし、STSへの頻繁な呼び出しにより、スロットリングが発生する場合があります。 この場合、一時的なアクセス資格情報をキャッシュし、有効期間が終了する前に更新することを推奨します。 詳細については、「STSの概要」をご参照ください。
アプリケーションサーバーからPostObjectの署名とPOSTポリシーを取得する
アップロードするオブジェクトの属性を制限するシナリオでは、PostObject操作を呼び出すために必要な情報をアプリケーションサーバーから取得する必要があります。 必要な情報には、署名とPOSTポリシーが含まれます。 クライアントは、取得した情報を使用して、OSS SDKを使用せずにオブジェクトをOSSに直接アップロードできます。 サーバーによって生成されたポリシーを使用して、オブジェクトのサイズやタイプなど、アップロードできるオブジェクトの属性を制限できます。 このソリューションは、HTMLフォームを使用したオブジェクトのアップロードに適しています。 このソリューションは、マルチパートアップロードと再開可能アップロードをサポートしていません。 詳細は、「PostObject」をご参照ください。
アプリケーションサーバーからPutObjectの署名付きURLを取得
単純なオブジェクトアップロードのシナリオでは、アプリケーションサーバーでOSS SDKを使用して、PutObject操作を呼び出すために必要な署名付きURLを取得できます。 その後、クライアントは署名付きURLを使用して、OSS SDKを使用せずにオブジェクトをアップロードできます。 このソリューションは、マルチパートアップロードと再開可能アップロードには適していません。 アプリケーションサーバは、各部分の署名付きURLを生成し、署名付きURLをクライアントに返す。 これは、アプリケーションサーバとの対話の数およびネットワーク要求の複雑さを増大させる。 さらに、クライアントは、部分の内容または順序を修正することができ、その結果、無効な結合オブジェクトが生じる。 詳細については、「署名V1を使用した署名付きURLの作成」をご参照ください。
アプリケーションサーバーのSTSから一時的なアクセス資格情報を取得する
次の図は、アプリケーションサーバーから返されたSTSの一時的なアクセス資格情報を使用して、クライアントからオブジェクトをOSSにアップロードする方法を示しています。
クライアントは、アプリケーションサーバーに一時的なアクセス資格情報を要求します。
アプリケーションサーバーはSTS SDKを使用してAssumeRole操作を呼び出し、一時的なアクセス資格情報を取得します。
STSは一時的なアクセス資格情報を生成してアプリケーションサーバーに返します。
アプリケーションサーバーは、一時的なアクセス資格情報をクライアントに返します。
クライアントは、OSS SDKを使用して、一時的なアクセス資格情報を使用してオブジェクトをOSSにアップロードします。
OSSは成功応答をクライアントに返します。
デモプロジェクト
sts.zip
例
サーバー側のサンプルコード
次のサンプルコードは、アプリケーションサーバーがSTSから一時的なアクセス資格情報を取得する方法の例を示しています。
クライアント側のサンプルコード
次のサンプルコードは、一時的なアクセス資格情報を使用して、webクライアントからオブジェクトをOSSにアップロードする方法の例を示しています。
アプリケーションサーバーからPostObjectの署名とPOSTポリシーを取得する
次の図は、アプリケーションサーバーから取得した署名とPOSTポリシーを使用して、クライアントからOSSにオブジェクトをアップロードする方法を示しています。
クライアントは、署名やPOSTポリシーなどの情報をアプリケーションサーバーに要求します。
アプリケーションサーバーは、署名やPOSTポリシーなどの情報を生成してクライアントに返します。
クライアントは、署名やPOSTポリシーなどの情報を使用してPostObject操作を呼び出し、HTMLフォームを使用してオブジェクトをOSSにアップロードします。
OSSは成功応答をクライアントに返します。
デモプロジェクト
postsignature.zip
例
サーバー側のサンプルコード
次のサンプルコードは、アプリケーションサーバーから署名とPOSTポリシーを取得する方法の例を示しています。
osのインポート
hashlibからsha1をshaとしてインポート
jsonのインポート
インポートbase64
hmacのインポート
datetimeのインポート
インポート時間
# OSS_ACCESS_KEY_ID環境変数を設定します。
access_key_id = os.environ.get('OSS_ACCESS_KEY_ID ')
# OSS_ACCESS_KEY_SECRET環境変数を設定します。
access_key_secret = os.environ.get('OSS_ACCESS_KEY_SECRET ')
# <YOUR_BUCKET> をバケットの名前に置き換えます。
bucket = '<YOUR_BUCKET>'
# ホストをBucketName.Endpoint形式の値に設定します。 <YOUR_BUCKET> をバケットの名前に置き換えます。 <YOUR_ENDPOINT> を、バケットが配置されているリージョンのエンドポイントに置き換えます。
host = 'https://<YOUR_BUCKET>.<YOUR_ENDPOINT>'
# OSSにアップロードするオブジェクトの名前にプレフィックスを指定します。
upload_dir = 'user-dir-prefix/'
# 有効期間を指定します。 単位は秒です。
expire_time = 3600
def generate_expailation (秒):
"""
有効期限は、指定された有効期間に基づいて計算されます。 単位は秒です。
: param seconds: 有効期間 (秒) 。
: return: ISO 8601標準の時間文字列。 例: 2014-12-01T12:00:00.000Z
"""
now = int(time.time())
expiration_time = now + 秒
gmt = datetime.datetime.utcfromtimestamp(expiration_time). isofformat ()
gmt += 'Z'
gmtを返す
def generate_signature(access_key_secret、有効期限、条件、policy_extra_props=なし):
"""
署名文字列を生成します。
: param access_key_secret: バケットへのアクセス権限を持つAccessKeyシークレット。
: param expiration: 署名の有効期限が切れる時刻。 時刻を ISO 8601 規格 (yyyy-MM-ddTHH:mm:ssZ) の形式で指定します。 例: 2014-12-01T12:00:00.000Z
: param条件: フォームのアップロード時に指定できる値を制限するために使用できるポリシー条件。
: param policy_extra_props: 追加のポリシーパラメーター。 追加のパラメータをdictとして渡すことができます。
: return: 署名文字列。
"""
policy_dict = {
'expiration': 有効期限、
'conditions': 条件
}
policy_extra_propsがNoneでない場合:
policy_dict.update(policy_extra_props)
policy = json.dumps(policy_dict).strip()
policy_encode = base64.b64encode(policy.encode())
h = hmac.new(access_key_secret.encode(), policy_encode, sha)
sign_result = base64.b64encode(h.digest()).strip()
リターンsign_result.decode()
def generate_upload_params():
policy = {
# ポリシーの有効期間を指定します。
"expailation": generate_expailation (expire_time) 、
# ポリシー条件を指定します。
"conditions": [
# success_action_redirectが指定されていない場合、オブジェクトのアップロード後にHTTPステータスコード204が返されます。
["eq" 、"$success_action_status" 、"200"] 、
# フォームフィールドの値は、指定されたプレフィックスで始まる必要があります。 たとえば、キーフォームフィールドの値がuser/user1で始まる場合、条件は ["starts-with", "$key", "user/user1"] です。
["starts-with" 、"$key" 、upload_dir] 、
# アップロードできるオブジェクトの最小サイズと最大サイズを指定します。 単位:バイト
["content-length-range", 1, 1000000],
# アップロードするオブジェクトのタイプを指定したイメージタイプに設定します。
["in", "$content-type", ["image/jpg", "image/png"]]
]
}
signature = generate_signature(access_key_secret, policy.get('expiration'), policy.get('conditions'))
response = {
'policy': base64.b64encode(json.dumps(policy).encode('utf-8 ')).decode() 、
'ossAccessKeyId': access_key_id、
'signature': signature、
'host ': ホスト、
'dir': upload_dir
# 追加のパラメーターを指定します。
}
を返すjson.dumps (応答)
クライアント側のサンプルコード
次のサンプルコードは、署名とPOSTポリシーを使用してwebクライアントからOSSにオブジェクトをアップロードする方法の例を示しています。
const form = document.querySelector('form');
const fileInput = document.querySelector('#file');
form.addEventListener('submit', (event) => {
event.preventDefault();
let file = fileInput.files[0];
let filename = fileInput.files[0].name;
fetch('/get_post_signature_for_oss_upload', { method: 'GET' })
. then(response => response.json())
. その後 (data => {
const formData=新しいFormData();
formData.append('name',filename);
formData.append('policy', data.policy);
formData.append('OSSAccessKeyId', data.ossAccessKeyId);
formData.append('success_action_status '、'200');
formData.append('signature', data.signature);
formData.append('key ', data.dir + filename);
// fileは最後のフォームフィールドでなければなりません。 他のフォームフィールドに特別な注文は必要ありません。
formData.append('file' 、ファイル);
fetch(data.host, { method: 'POST', body: formData },).then((res) => {
console.log(res);
alert ('Object Uploaded');
});
})
. catch(error => {
console.log('OSSアップロードパラメータの取得中にエラーが発生しました:' 、エラー);
});
});
アプリケーションサーバーからPutObjectの署名付きURLを取得する
次の図は、アプリケーションサーバーから取得した署名付きURLを使用して、クライアントからオブジェクトをOSSにアップロードする方法を示しています。
クライアントは、アプリケーションサーバーに署名付きURLを要求します。
アプリケーションサーバーは、OSS SDKを使用してPUTリクエストの署名付きURLを生成し、署名付きURLをクライアントに返します。
クライアントは署名付きURLを使用してPutObject操作を呼び出し、オブジェクトをOSSにアップロードします。
OSSは成功応答をクライアントに返します。
デモプロジェクト
presignedurl.zip
例
サーバー側のサンプルコード
次のサンプルコードは、アプリケーションサーバーから署名付きURLを取得する方法の例を示しています。
クライアント側のサンプルコード
次のサンプルコードは、署名付きURLを使用してwebクライアントからOSSにオブジェクトをアップロードする方法の例を示しています。
ベストプラクティス
クライアントからOSSにデータをアップロードするためのベストプラクティスについては、以下のトピックを参照してください。