- 印刷する
- PDF
Object Storage API
- 印刷する
- PDF
Classic/VPC環境で利用できます。
Amazon S3 APIと互換する Object Storage APIのサポート情報と APIの共通呼び出しおよび認証方法を確認します。S3 APIを利用して NAVERクラウドプラットフォームの Object Storageで作成されるリクエストは、AWSの認証(Authorization)ヘッダの実装体を使って認証します。Object Storageがサポートする認証方式には Signature Version 2、Signature Version 4があり、本ガイドでは Version 4を基準に説明します。
サポートする API
Object Storage APIはストレージの管理と使用時に必要な様々な機能を制御できます。サポートするオペ―レーションリストは Object Storage APIガイドでご確認ください。
API呼び出し
Object Storage APIの呼び出し段階は、次の通りです。
1. 認証キーの作成
2. 呼び出しドメインの確認
3. 認証
4. 呼び出し
1. 認証キーの作成
Object Storage APIを使用するために認証キーを作成する方法は、Ncloud APIの認証キーを作成する方法と同じです。Ncloud APIの1. 認証キーの作成をご参照ください。
2. 呼び出しドメインの確認
HTTPと HTTPSプロトコルを両方ともサポートしますが、 データ保護のため、HTTPSの使用をお勧めします。リージョン別の呼び出しドメインに関する情報は、次の通りです。
リージョン | リージョン名 | 呼び出しドメイン |
---|---|---|
韓国 | kr-standard | https://kr.object.ncloudstorage.com |
アメリカ西部(New) | us-standard | https://us.object.ncloudstorage.com |
シンガポール(New) | sg-standard | https://sg.object.ncloudstorage.com |
日本(New) | jp-standard | https://jp.object.ncpstorage.com |
ドイツ(New) | de-standard | https://de.object.ncloudstorage.com |
3. 認証
認証ヘッダ(Authorization)を作成する手順は、次の通りです。
1) 標準化リクエストの作成(Canonical Request)
2) 署名する文字列の作成(String to Sign)
3) 認証キーの作成(Signing Key)
4) 署名作成(Signature)
5) 認証ヘッダの作成(Authorization)
1) 標準化リクエストの作成(Canonical Request)
標準化リクエスト(Canonical Request)の構成と各項目に関する説明は、次の通りです。
<HTTPMethod>\n
<CanonicalURI>\n
<CanonicalQueryString>\n
<CanonicalHeaders>\n
<SignedHeaders>\n
<HashedPayload>
HTTPMethod
使用する HTTPメソッドを宣言します。例) PUT
CanonicalURI
アクセスするリソースを標準化した方式(URI-encoded)で定義します。例) /path/object
- オブジェクトキー名にアルファベット、数字、「-」、「_」、「~」、「.」、「/」文字をエンコードできません。
- 空白文字は「%20」でエンコードされる必要があります。
CanonicalQueryString
リクエストパラメータがある場合は、標準化した方式(URI-encoded)で定義し、アルファベット順に並べます。
UriEncode("marker")+"="+UriEncode("someMarker")+"&"+ UriEncode("max-keys")+"="+UriEncode("20") + "&" + UriEncode("prefix")+"="+UriEncode("somePrefix")
CanonicalHeaders
リクエストに含まれるヘッダ名と値を標準化した方式で定義します。ヘッダ名は全て小文字に変換し、ヘッダ値の前後スペースを削除します。各ヘッダ項目の末尾に改行文字\n
を挿入します。この時、ヘッダ名でアルファベット順にソートする必要があります。
host
ヘッダとx-amz-
で始まるヘッダは必須項目であり、より正確なデータ整合性を確認するために、全てのヘッダを含めることをお勧めします。
Signature Version 4の認証のすべてのリクエストでは x-amz-content-sha256
ヘッダを含めます。データ(payload)に対するハッシュ値を入力する必要があり、2つのオプションを提供しています。
*署名されたデータ(signed payload): データ(payload)の SHA256ハッシュの16進数の値を入力します。データ(payload)がない場合、空の文字列のハッシュ値を入力する必要があります。
*署名されていないデータ(signed payload): データ(payload)を署名しない場合、「x-amz-content-sha256」ヘッダの値で「UNSIGNED-PAYLOAD」文字列を入力します。
```
Lowercase(<HeaderName1>)+":"+Trim(<value>)+"\n"
Lowercase(<HeaderName2>)+":"+Trim(<value>)+"\n"
```
SignedHeaders
リクエストに含まれるヘッダ名を並べます。ヘッダ名は全て小文字に変換し、アルファベット順に並べます。各ヘッダ名の区切り文字として、セミコロン(「;」)を入力します。
```
host;x-amz-content-sha256;x-amz-date
```
HashedPayload
データ(payload)の SHA256ハッシュの16進数の値を入力します。(x-amz-content-sha256
ヘッダ値と同様)リクエストデータ(payload)がない場合、空の文字列のハッシュ値を入力する必要があります。データ(payload)を署名しない場合、UNSIGNED-PAYLOAD
文字列を入力します。
```
Hex(SHA256Hash(<payload>)
or
Hex(SHA256Hash(""))
or
UNSIGNED-PAYLOAD
```
2) 署名する文字列の作成(String to Sign)
署名する文字列(String)の構成と各項目に関する説明は、次の通りです。
AWS4-HMAC-SHA256\n
<Timestamp>\n
<Scope>\n
Hex(SHA256Hash(<CanonicalRequest>))
Timestamp
UTC(Coordinated Universal Time)を基準に、ISO 8601の国際標準規格に基づいて表示します。例) 20161128T152924Z
Scope
Scope文字列は、以下のように構成されています。
```
<Date>/<Region>/s3/aws4_request
```
*Date: 「YYYYMMDD」形式で入力します。
*Region: リージョン名を入力します。リージョン名は、2. 呼び出しドメインの確認で確認できます。リージョン名は必須入力項目ですが、NAVERクラウドプラットフォームの Object Storageでは、ドメインでリージョンを区分するため、リージョン名の整合性は確認しません。
CanonicalRequest
作成した標準化リクエスト(Canonical Request)の SHA256ハッシュの16進数の値を入力します。
3) 署名キーの作成(Signing Key)
署名者(Key)の構成と各項目に関する説明は、次の通りです。
kSecret = <SecretKey>
kDate = HMAC-SHA256("AWS4" + kSecret, <Date>)
kRegion = HMAC-SHA256(kDate, <Region>)
kService = HMAC-SHA256(kRegion, "s3")
kSigning = HMAC-SHA256(kService, "aws4_request")
SecretKey
API認証キーのうち、Secret Keyを入力します。NAVERクラウドプラットフォームポータルの [マイページ] > [アカウント管理] > [認証キー管理] で確認できます。
Date
YYYYMMDD
形式で入力します。
Region
リージョン名を入力します。リージョン名は、2. 呼び出しドメインの確認で確認できます。リージョン名は必須入力項目ですが、NAVERクラウドプラットフォームの Object Storageでは、ドメインでリージョンを区分するため、リージョン名の整合性は確認しません。
4) 署名の作成(Signature)
署名(Signature)の構成と各項目に関する説明は、次の通りです。
Hex(HMAC-SHA256(<SigningKey>, <StringToSign>))
Signing Key
署名キーの HMAC-SHA256ハッシュを計算して16進数で表示します。
StringToSign
署名する文字列の HMAC-SHA256ハッシュを計算して16進数で表示します。
5) 認証ヘッダの作成(Authorization)
認証ヘッダ(Authorization)の構成と各項目に関する説明は、次の通りです。
Authorization: AWS4-HMAC-SHA256 Credential=<AccessKeyID>/<Scope>, SignedHeaders=<SignedHeaders>, Signature=<Signature>
AccessKeyID
API認証キーのうち、Access Key IDを入力します。NAVERクラウドプラットフォームポータルの [マイページ] > [アカウント管理] > [認証キー管理] で確認できます。
Scope
Scope文字列は、以下のように構成されています。
```
<Date>/<Region>/s3/aws4_request
```
*Date: 「YYYYMMDD」形式で入力します。
*Region: リージョン名を入力します。リージョン名は、2. 呼び出しドメインの確認で確認できます。リージョン名は必須入力項目ですが、NAVERクラウドプラットフォームの Object Storageでは、ドメインでリージョンを区分するため、リージョン名の整合性は確認しません。
SignedHeaders
リクエストに含まれるヘッダ名を並べます。ヘッダ名は全て小文字に変換し、アルファベット順に並べます。各ヘッダ名の区切り文字として、セミコロン(「;」)を入力します。 host;x-amz-content-sha256;x-amz-date
Signature
4)署名の作成(Signature)で作成した署名(Signature)を入力します。
言語別の認証ヘッダ(Authorization)の作成例は、次の通りです。
public class ObjectStorageSample {
private static byte[] sign(String stringData, byte[] key) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
byte[] data = stringData.getBytes(CHARSET_NAME);
Mac e = Mac.getInstance(HMAC_ALGORITHM);
e.init(new SecretKeySpec(key, HMAC_ALGORITHM));
return e.doFinal(data);
}
private static String hash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest e = MessageDigest.getInstance(HASH_ALGORITHM);
e.update(text.getBytes(CHARSET_NAME));
return Hex.encodeHexString(e.digest());
}
private static String getStandardizedQueryParameters(String queryString) throws UnsupportedEncodingException {
TreeMap<String, String> sortedQueryParameters = new TreeMap<>();
// sort by key name
if (queryString != null && !queryString.isEmpty()) {
String[] queryStringTokens = queryString.split("&");
for (String field : queryStringTokens) {
String[] fieldTokens = field.split("=");
if (fieldTokens.length > 0) {
if (fieldTokens.length > 1) {
sortedQueryParameters.put(fieldTokens[0], fieldTokens[1]);
} else {
sortedQueryParameters.put(fieldTokens[0], "");
}
}
}
}
StringBuilder standardizedQueryParametersBuilder = new StringBuilder();
int count = 0;
for (String key : sortedQueryParameters.keySet()) {
if (count > 0) {
standardizedQueryParametersBuilder.append("&");
}
standardizedQueryParametersBuilder.append(key).append("=");
if (sortedQueryParameters.get(key) != null && !sortedQueryParameters.get(key).isEmpty()) {
standardizedQueryParametersBuilder.append(URLEncoder.encode(sortedQueryParameters.get(key), CHARSET_NAME));
}
count++;
}
return standardizedQueryParametersBuilder.toString();
}
private static TreeMap<String, String> getSortedHeaders(Header[] headers) {
TreeMap<String, String> sortedHeaders = new TreeMap<>();
// sort by header name
for (Header header : headers) {
String headerName = header.getName().toLowerCase();
sortedHeaders.put(headerName, header.getValue());
}
return sortedHeaders;
}
private static String getSignedHeaders(TreeMap<String, String> sortedHeaders) {
StringBuilder signedHeadersBuilder = new StringBuilder();
for (String headerName : sortedHeaders.keySet()) {
signedHeadersBuilder.append(headerName.toLowerCase()).append(";");
}
String s = signedHeadersBuilder.toString();
if (s.endsWith(";")) {
s = s.substring(0, s.length() - 1);
}
return s;
}
private static String getStandardizedHeaders(TreeMap<String, String> sortedHeaders) {
StringBuilder standardizedHeadersBuilder = new StringBuilder();
for (String headerName : sortedHeaders.keySet()) {
standardizedHeadersBuilder.append(headerName.toLowerCase()).append(":").append(sortedHeaders.get(headerName)).append("\n");
}
return standardizedHeadersBuilder.toString();
}
private static String getCanonicalRequest(HttpUriRequest request, String standardizedQueryParameters, String standardizedHeaders, String signedHeaders) {
StringBuilder canonicalRequestBuilder = new StringBuilder().append(request.getMethod()).append("\n")
.append(request.getURI().getPath()).append("\n")
.append(standardizedQueryParameters).append("\n")
.append(standardizedHeaders).append("\n")
.append(signedHeaders).append("\n")
.append(UNSIGNED_PAYLOAD);
return canonicalRequestBuilder.toString();
}
private static String getScope(String datestamp, String regionName) {
StringBuilder scopeBuilder = new StringBuilder().append(datestamp).append("/")
.append(regionName).append("/")
.append(SERVICE_NAME).append("/")
.append(REQUEST_TYPE);
return scopeBuilder.toString();
}
private static String getStringToSign(String timestamp, String scope, String canonicalRequest) throws NoSuchAlgorithmException, UnsupportedEncodingException {
StringBuilder stringToSignBuilder = new StringBuilder(AWS_ALGORITHM)
.append("\n")
.append(timestamp).append("\n")
.append(scope).append("\n")
.append(hash(canonicalRequest));
return stringToSignBuilder.toString();
}
private static String getSignature(String secretKey, String datestamp, String regionName, String stringToSign) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
byte[] kSecret = ("AWS4" + secretKey).getBytes(CHARSET_NAME);
byte[] kDate = sign(datestamp, kSecret);
byte[] kRegion = sign(regionName, kDate);
byte[] kService = sign(SERVICE_NAME, kRegion);
byte[] signingKey = sign(REQUEST_TYPE, kService);
return Hex.encodeHexString(sign(stringToSign, signingKey));
}
private static String getAuthorization(String accessKey, String scope, String signedHeaders, String signature) {
String signingCredentials = accessKey + "/" + scope;
String credential = "Credential=" + signingCredentials;
String signerHeaders = "SignedHeaders=" + signedHeaders;
String signatureHeader = "Signature=" + signature;
StringBuilder authHeaderBuilder = new StringBuilder().append(AWS_ALGORITHM).append(" ")
.append(credential).append(", ")
.append(signerHeaders).append(", ")
.append(signatureHeader);
return authHeaderBuilder.toString();
}
private static void authorization(HttpUriRequest request, String regionName, String accessKey, String secretKey) throws Exception {
Date now = new Date();
DATE_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
TIME_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
String datestamp = DATE_FORMATTER.format(now);
String timestamp = TIME_FORMATTER.format(now);
request.addHeader("X-Amz-Date", timestamp);
request.addHeader("X-Amz-Content-Sha256", UNSIGNED_PAYLOAD);
String standardizedQueryParameters = getStandardizedQueryParameters(request.getURI().getQuery());
TreeMap<String, String> sortedHeaders = getSortedHeaders(request.getAllHeaders());
String signedHeaders = getSignedHeaders(sortedHeaders);
String standardizedHeaders = getStandardizedHeaders(sortedHeaders);
String canonicalRequest = getCanonicalRequest(request, standardizedQueryParameters, standardizedHeaders, signedHeaders);
System.out.println("> canonicalRequest :");
System.out.println(canonicalRequest);
String scope = getScope(datestamp, regionName);
String stringToSign = getStringToSign(timestamp, scope, canonicalRequest);
System.out.println("> stringToSign :");
System.out.println(stringToSign);
String signature = getSignature(secretKey, datestamp, regionName, stringToSign);
String authorization = getAuthorization(accessKey, scope, signedHeaders, signature);
request.addHeader("Authorization", authorization);
}
private static void putObject(String bucketName, String objectName, String localFilePath) throws Exception {
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPut request = new HttpPut(ENDPOINT + "/" + bucketName + "/" + objectName);
request.addHeader("Host", request.getURI().getHost());
request.setEntity(new FileEntity(new File(localFilePath)));
authorization(request, REGION_NAME, ACCESS_KEY, SECRET_KEY);
HttpResponse response = httpClient.execute(request);
System.out.println("Response : " + response.getStatusLine());
}
private static void getObject(String bucketName, String objectName, String localFilePath) throws Exception {
HttpClient httpClient = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(ENDPOINT + "/" + bucketName + "/" + objectName);
request.addHeader("Host", request.getURI().getHost());
authorization(request, REGION_NAME, ACCESS_KEY, SECRET_KEY);
HttpResponse response = httpClient.execute(request);
System.out.println("Response : " + response.getStatusLine());
InputStream is = response.getEntity().getContent();
File targetFile = new File(localFilePath);
OutputStream os = new FileOutputStream(targetFile);
byte[] buffer = new byte[8 * 1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
is.close();
os.close();
}
private static void listObjects(String bucketName, String queryString) throws Exception {
HttpClient httpClient = HttpClientBuilder.create().build();
URI uri = new URI(ENDPOINT + "/" + bucketName + "?" + queryString);
HttpGet request = new HttpGet(uri);
request.addHeader("Host", request.getURI().getHost());
authorization(request, REGION_NAME, ACCESS_KEY, SECRET_KEY);
HttpResponse response = httpClient.execute(request);
System.out.println("> Response : " + response.getStatusLine());
int i;
InputStream is = response.getEntity().getContent();
StringBuffer buffer = new StringBuffer();
byte[] b = new byte[4096];
while ((i = is.read(b)) != -1) {
buffer.append(new String(b, 0, i));
}
System.out.println(buffer.toString());
}
private static final String CHARSET_NAME = "UTF-8";
private static final String HMAC_ALGORITHM = "HmacSHA256";
private static final String HASH_ALGORITHM = "SHA-256";
private static final String AWS_ALGORITHM = "AWS4-HMAC-SHA256";
private static final String SERVICE_NAME = "s3";
private static final String REQUEST_TYPE = "aws4_request";
private static final String UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyyMMdd");
private static final SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("yyyyMMdd\'T\'HHmmss\'Z\'");
private static final String REGION_NAME = "kr-standard";
private static final String ENDPOINT = "https://kr.object.ncloudstorage.com";
private static final String ACCESS_KEY = "ACCESS_KEY_ID";
private static final String SECRET_KEY = "SECRET_KEY";
public static void main(String[] args) throws Exception {
String bucketName = "sample-bucket";
String objectName = "sample-object.txt";
String sourceFilePath = "/tmp/source.txt";
String targetFilePath = "/tmp/target.txt";
putObject(bucketName, objectName, sourceFilePath);
getObject(bucketName, objectName, targetFilePath);
String queryString = "max-keys=10&delimiter=/";
listObjects(bucketName, queryString);
}
}
import hashlib
import hmac
import datetime
import requests
import urllib
def get_hash(key, msg):
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
def create_signed_headers(headers):
signed_headers = []
for k in sorted(headers):
signed_headers.append('%s;' % k)
return ''.join(signed_headers)[:-1]
def create_standardized_headers(headers):
signed_headers = []
for k in sorted(headers):
signed_headers.append('%s:%s\n' % (k, headers[k]))
return ''.join(signed_headers)
def create_standardized_query_parameters(request_parameters):
standardized_query_parameters = []
if request_parameters:
for k in sorted(request_parameters):
standardized_query_parameters.append('%s=%s' % (k, urllib.quote(request_parameters[k], safe='')))
return '&'.join(standardized_query_parameters)
else:
return ''
class ObjectStorageSample:
def __init__(self):
self.region = 'kr-standard'
self.endpoint = 'https://kr.object.ncloudstorage.com'
self.host = 'kr.object.ncloudstorage.com'
self.access_key = 'ACCESS_KEY_ID'
self.secret_key = 'SECRET_KEY'
self.payload_hash = 'UNSIGNED-PAYLOAD'
self.hashing_algorithm = 'AWS4-HMAC-SHA256'
self.service_name = 's3'
self.request_type = 'aws4_request'
self.time_format = '%Y%m%dT%H%M%SZ'
self.date_format = '%Y%m%d'
def _create_credential_scope(self, date_stamp):
return date_stamp + '/' + self.region + '/' + self.service_name + '/' + self.request_type
def _create_canonical_request(self, http_method, request_path, request_parameters, headers):
standardized_query_parameters = create_standardized_query_parameters(request_parameters)
standardized_headers = create_standardized_headers(headers)
signed_headers = create_signed_headers(headers)
canonical_request = (http_method + '\n' +
request_path + '\n' +
standardized_query_parameters + '\n' +
standardized_headers + '\n' +
signed_headers + '\n' +
self.payload_hash)
print('canonical_request:\n%s\n' % canonical_request)
return canonical_request
def _create_string_to_sign(self, time_stamp, credential_scope, canonical_request):
string_to_sign = (self.hashing_algorithm + '\n' +
time_stamp + '\n' +
credential_scope + '\n' +
hashlib.sha256(canonical_request.encode('utf-8')).hexdigest())
print('string_to_sign:\n%s\n' % string_to_sign)
return string_to_sign
def _create_signature_key(self, date_stamp):
key_date = get_hash(('AWS4' + self.secret_key).encode('utf-8'), date_stamp)
key_string = get_hash(key_date, self.region)
key_service = get_hash(key_string, self.service_name)
key_signing = get_hash(key_service, self.request_type)
return key_signing
def _create_authorization_header(self, headers, signature_key, string_to_sign, credential_scope):
signed_headers = create_signed_headers(headers)
signature = hmac.new(signature_key, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()
return (self.hashing_algorithm + ' ' +
'Credential=' + self.access_key + '/' + credential_scope + ', ' +
'SignedHeaders=' + signed_headers + ', ' +
'Signature=' + signature)
def _sign(self, http_method, request_path, headers, time, request_parameters=None):
time_stamp = time.strftime(self.time_format)
date_stamp = time.strftime(self.date_format)
credential_scope = self._create_credential_scope(date_stamp)
canonical_request = self._create_canonical_request(http_method, request_path, request_parameters, headers)
string_to_sign = self._create_string_to_sign(time_stamp, credential_scope, canonical_request)
signature_key = self._create_signature_key(date_stamp)
headers['authorization'] = self._create_authorization_header(headers, signature_key, string_to_sign, credential_scope)
def put_object(self, bucket_name, object_name, source_file_path, request_parameters=None):
http_method = 'PUT'
with open(source_file_path) as f:
time = datetime.datetime.utcnow()
time_stamp = time.strftime(self.time_format)
headers = {'x-amz-date': time_stamp,
'x-amz-content-sha256': self.payload_hash,
'host': self.host}
request_path = '/%s/%s' % (bucket_name, object_name)
self._sign(http_method, request_path, headers, time, request_parameters)
request_url = self.endpoint + request_path
r = requests.put(request_url, headers=headers, params=request_parameters, data=f.read())
print('Response code: %d' % r.status_code)
def get_object(self, bucket_name, object_name, target_file_path, request_parameters=None):
http_method = 'GET'
time = datetime.datetime.utcnow()
time_stamp = time.strftime(self.time_format)
headers = {'x-amz-date': time_stamp,
'x-amz-content-sha256': self.payload_hash,
'host': self.host}
request_path = '/%s/%s' % (bucket_name, object_name)
self._sign(http_method, request_path, headers, time, request_parameters)
request_url = self.endpoint + request_path
r = requests.get(request_url, headers=headers, params=request_parameters, stream=True)
print('Response code: %d' % r.status_code)
if r.status_code == 200:
with open(target_file_path, 'wb') as f:
f.write(r.content)
def list_objects(self, bucket_name, request_parameters=None):
http_method = 'GET'
time = datetime.datetime.utcnow()
time_stamp = time.strftime(self.time_format)
headers = {'x-amz-date': time_stamp,
'x-amz-content-sha256': self.payload_hash,
'host': self.host}
request_path = '/%s' % bucket_name
self._sign(http_method, request_path, headers, time, request_parameters)
request_url = self.endpoint + request_path
r = requests.get(request_url, headers=headers, params=request_parameters)
print('Response code: %d' % r.status_code)
print('Response content:\n%s' % r.content)
if __name__ == '__main__':
sample = ObjectStorageSample()
sample.put_object('sample-bucket', 'sample-object.txt', '/tmp/source.txt')
sample.get_object('sample-bucket', 'sample-object.txt', '/tmp/target.txt')
sample.list_objects('sample-bucket', request_parameters={'max-keys': '10', 'delimiter': '/'})
4. 呼び出し
1.~3.の内容をもとに、APIを呼び出します。API呼び出しによる結果は成功か失敗で区分できます。レスポンスに成功した場合、返された結果を確認します。レスポンスに失敗した場合、エラーコードがリターンされます。返されたエラーコードを確認してから、呼び出しを再試行してください。
成功
API呼び出しに対するレスポンス処理方法については、Object Storage APIガイドをご参照ください。
失敗
呼び出しに失敗して返されるエラーコードには、共通のエラーコードとオペレーション別のエラーコードがあります。エラーコードについては、Object Storage APIガイドをご参照ください。