デフォルトでは、必要なアクセス権限があれば、新しいオブジェクトは同じ名前の既存のオブジェクトを上書きします。このトピックでは、シンプルアップロード、オブジェクトのコピー、マルチパートアップロードにおいて、リクエストヘッダー x-oss-forbid-overwrite を設定することでこの動作を防ぐ方法について説明します。
注意事項
このトピックでは、中国 (杭州) リージョンのパブリックエンドポイントを使用します。同じリージョン内の他の Alibaba Cloud サービスから OSS にアクセスするには、内部エンドポイントを使用します。サポートされているリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。
このトピックでは、アクセス認証情報は環境変数から取得します。アクセス認証情報の設定方法の詳細については、「アクセス認証情報の設定」をご参照ください。
このトピックでは、OSS エンドポイントを使用して OSSClient インスタンスを作成します。カスタムドメイン名または Security Token Service (STS) を使用して OSSClient インスタンスを作成する場合は、「一般的なシナリオの設定例」をご参照ください。
シンプルアップロード
次のコードは、シンプルアップロード中に同名のオブジェクトが上書きされるのを防ぐ方法を示しています。
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import java.io.ByteArrayInputStream;
public class Demo {
public static void main(String[] args) throws Exception {
// この例では、中国 (杭州) リージョンのエンドポイントを使用します。実際のエンドポイントに置き換えてください。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 環境変数からアクセス認証情報を取得します。このコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// バケット名を指定します。例:examplebucket。
String bucketName = "examplebucket";
// オブジェクトの完全なパスを指定します。完全なパスにバケット名を含めることはできません。
String objectName = "exampledir/object";
String content = "Hello OSS!";
// バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。
String region = "cn-hangzhou";
// OSSClient インスタンスを作成します。
// OSSClient インスタンスが不要になったら、shutdown メソッドを呼び出してリソースを解放します。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
// PutObjectRequest オブジェクトを作成します。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
// アップロード中に同名のオブジェクトを上書きするかどうかを指定します。
// x-oss-forbid-overwrite を指定しない場合、デフォルトで同名のオブジェクトは上書きされます。
// x-oss-forbid-overwrite を false に設定すると、同名のオブジェクトは上書きされます。
// x-oss-forbid-overwrite を true に設定すると、同名のオブジェクトは上書きされません。同名のオブジェクトが既に存在する場合、プログラムはエラーを報告します。
ObjectMetadata metadata = new ObjectMetadata();
metadata.setHeader("x-oss-forbid-overwrite", "true");
putObjectRequest.setMetadata(metadata);
// ファイルをアップロードします。
ossClient.putObject(putObjectRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}ファイルのコピー
CopyObjectRequest を使用した小規模なオブジェクトのコピー
次のコードは、CopyObjectRequest を使用して小規模なオブジェクトをコピーする際に、同名のオブジェクトが上書きされるのを防ぐ方法を示しています。
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.model.*; public class Demo { public static void main(String[] args) throws Exception { // この例では、中国 (杭州) リージョンのエンドポイントを使用します。実際のエンドポイントに置き換えてください。 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 環境変数からアクセス認証情報を取得します。このコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。 EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // ソースバケット名を指定します。 String sourceBucketName = "srcexamplebucket"; // ソースオブジェクトの完全なパスを指定します。完全なパスにバケット名を含めることはできません。 String sourceObjectName = "srcexampleobject.txt"; // 宛先バケット名を指定します。宛先バケットはソースバケットと同じリージョンにある必要があります。 String destinationBucketName = "desexamplebucket"; // 宛先オブジェクトの完全なパスを指定します。完全なパスにバケット名を含めることはできません。 String destinationObjectName = "desexampleobject.txt"; // バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。 String region = "cn-hangzhou"; // OSSClient インスタンスを作成します。 // OSSClient インスタンスが不要になったら、shutdown メソッドを呼び出してリソースを解放します。 ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // CopyObjectRequest オブジェクトを作成します。 CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceObjectName, destinationBucketName, destinationObjectName); // 新しいオブジェクトのメタデータを設定します。 ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType("text/html"); // コピー操作中に同名のオブジェクトを上書きするかどうかを指定します。 // x-oss-forbid-overwrite を指定しない場合、デフォルトで同名のオブジェクトは上書きされます。 // x-oss-forbid-overwrite を false に設定すると、同名のオブジェクトは上書きされます。 // x-oss-forbid-overwrite を true に設定すると、同名のオブジェクトは上書きされません。同名のオブジェクトが既に存在する場合、プログラムはエラーを報告します。 metadata.setHeader("x-oss-forbid-overwrite", "true"); copyObjectRequest.setNewObjectMetadata(metadata); // オブジェクトをコピーします。 CopyObjectResult result = ossClient.copyObject(copyObjectRequest); System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified()); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message:" + oe.getErrorMessage()); System.out.println("Error Code:" + oe.getErrorCode()); System.out.println("Request ID:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } }ラージオブジェクトのコピー
次のコードは、マルチパートコピーを使用してラージオブジェクトをコピーする際に、同名のオブジェクトが上書きされるのを防ぐ方法を示しています。
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.model.*; import java.util.ArrayList; import java.util.List; public class Demo { public static void main(String[] args) throws Exception { // この例では、中国 (杭州) リージョンのエンドポイントを使用します。実際のエンドポイントに置き換えてください。 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 環境変数からアクセス認証情報を取得します。このコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。 EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // ソースバケット名を指定します。 String sourceBucketName = "srcexamplebucket"; // ソースオブジェクトの完全なパスを指定します。完全なパスにバケット名を含めることはできません。 String sourceObjectName = "srcexampleobject.txt"; // 宛先バケット名を指定します。宛先バケットはソースバケットと同じリージョンにある必要があります。 String destinationBucketName = "desexamplebucket"; // 宛先オブジェクトの完全なパスを指定します。完全なパスにバケット名を含めることはできません。 String destinationObjectName = "desexampleobject.txt"; // バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。 String region = "cn-hangzhou"; // OSSClient インスタンスを作成します。 // OSSClient インスタンスが不要になったら、shutdown メソッドを呼び出してリソースを解放します。 ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { ObjectMetadata objectMetadata = ossClient.getObjectMetadata(sourceBucketName, sourceObjectName); // コピーするオブジェクトのサイズを取得します。 long contentLength = objectMetadata.getContentLength(); // パートサイズを 10 MB に設定します。 long partSize = 1024 * 1024 * 10; // パートの総数を計算します。 int partCount = (int) (contentLength / partSize); if (contentLength % partSize != 0) { partCount++; } System.out.println("total part count:" + partCount); // コピータスクを初期化します。InitiateMultipartUploadRequest で宛先オブジェクトのメタデータを指定できます。 InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(destinationBucketName, destinationObjectName); // コピー操作中に同名のオブジェクトを上書きするかどうかを指定します。 // x-oss-forbid-overwrite を指定しない場合、デフォルトで同名のオブジェクトは上書きされます。 // x-oss-forbid-overwrite を false に設定すると、同名のオブジェクトは上書きされます。 // x-oss-forbid-overwrite を true に設定すると、同名のオブジェクトは上書きされません。同名のオブジェクトが既に存在する場合、プログラムはエラーを報告します。 ObjectMetadata metadata = new ObjectMetadata(); metadata.setHeader("x-oss-forbid-overwrite", "true"); initiateMultipartUploadRequest.setObjectMetadata(metadata); InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest); String uploadId = initiateMultipartUploadResult.getUploadId(); // パートをコピーします。 List<PartETag> partETags = new ArrayList<PartETag>(); for (int i = 0; i < partCount; i++) { // 各パートのサイズを計算します。 long skipBytes = partSize * i; long size = partSize < contentLength - skipBytes ? partSize : contentLength - skipBytes; // UploadPartCopyRequest を作成します。UploadPartCopyRequest で条件を指定できます。 UploadPartCopyRequest uploadPartCopyRequest = new UploadPartCopyRequest(sourceBucketName, sourceObjectName, destinationBucketName, destinationObjectName); uploadPartCopyRequest.setUploadId(uploadId); uploadPartCopyRequest.setPartSize(size); uploadPartCopyRequest.setBeginIndex(skipBytes); uploadPartCopyRequest.setPartNumber(i + 1); UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest); // 返されたパートの ETag を partETags に保存します。 partETags.add(uploadPartCopyResult.getPartETag()); } // マルチパートコピータスクを完了します。 CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest( destinationBucketName, destinationObjectName, uploadId, partETags); // コピー操作中に同名のオブジェクトを上書きするかどうかを指定します。 // x-oss-forbid-overwrite を指定しない場合、デフォルトで同名のオブジェクトは上書きされます。 // x-oss-forbid-overwrite を false に設定すると、同名のオブジェクトは上書きされます。 // x-oss-forbid-overwrite を true に設定すると、同名のオブジェクトは上書きされません。同名のオブジェクトが既に存在する場合、プログラムはエラーを報告します。 completeMultipartUploadRequest.addHeader("x-oss-forbid-overwrite", "true"); ossClient.completeMultipartUpload(completeMultipartUploadRequest); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message:" + oe.getErrorMessage()); System.out.println("Error Code:" + oe.getErrorCode()); System.out.println("Request ID:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } }
マルチパートアップロード
次のコードは、マルチパートアップロード中に同名のオブジェクトが上書きされるのを防ぐ方法を示しています。
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) throws Exception {
// この例では、中国 (杭州) リージョンのエンドポイントを使用します。実際のエンドポイントに置き換えてください。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 環境変数からアクセス認証情報を取得します。このコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// バケット名を指定します。例:examplebucket。
String bucketName = "examplebucket";
// オブジェクトの完全なパスを指定します。完全なパスにバケット名を含めることはできません。
String objectName = "exampledir/object";
// バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。
String region = "cn-hangzhou";
// OSSClient インスタンスを作成します。
// OSSClient インスタンスが不要になったら、shutdown メソッドを呼び出してリソースを解放します。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
// InitiateMultipartUploadRequest オブジェクトを作成します。
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
// マルチパートアップロード中に同名のオブジェクトを上書きするかどうかを指定します。
// x-oss-forbid-overwrite を指定しない場合、デフォルトで同名のオブジェクトは上書きされます。
// x-oss-forbid-overwrite を false に設定すると、同名のオブジェクトは上書きされます。
// x-oss-forbid-overwrite を true に設定すると、同名のオブジェクトは上書きされません。同名のオブジェクトが既に存在する場合、プログラムはエラーを報告します。
ObjectMetadata metadata = new ObjectMetadata();
metadata.setHeader("x-oss-forbid-overwrite", "true");
request.setObjectMetadata(metadata);
// マルチパートアップロードを初期化します。
InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
// アップロード ID が返されます。これはマルチパートアップロードイベントの一意の識別子です。この ID を使用して、マルチパートアップロードの中止やクエリなどの関連操作を実行できます。
String uploadId = upresult.getUploadId();
// partETags は PartETag オブジェクトのコレクションです。PartETag は、パートの ETag とパート番号で構成されます。
List<PartETag> partETags = new ArrayList<PartETag>();
// パート数を計算します。
final long partSize = 1 * 1024 * 1024L; // 1 MB
final File sampleFile = new File("<localFile>");
long fileLength = sampleFile.length();
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
partCount++;
}
// ループでパートをアップロードします。
for (int i = 0; i < partCount; i++) {
long startPos = i * partSize;
long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
InputStream instream = new FileInputStream(sampleFile);
// アップロード済みのパートをスキップします。
instream.skip(startPos);
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(objectName);
uploadPartRequest.setUploadId(uploadId);
uploadPartRequest.setInputStream(instream);
// パートサイズを設定します。最後のパートを除き、各パートの最小サイズは 100 KB です。
uploadPartRequest.setPartSize(curPartSize);
// パート番号を設定します。アップロードされた各パートには、1 から 10,000 までの範囲のパート番号があります。パート番号がこの範囲外の場合、OSS は InvalidArgument エラーコードを返します。
uploadPartRequest.setPartNumber( i + 1);
// パートは順番にアップロードする必要はなく、異なるクライアントからアップロードできます。OSS はパート番号に基づいてパートを結合し、完全なオブジェクトを作成します。
UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
// 各パートがアップロードされると、OSS の応答に PartETag が含まれます。PartETag は partETags に保存されます。
partETags.add(uploadPartResult.getPartETag());
}
// CompleteMultipartUploadRequest オブジェクトを作成します。
// マルチパートアップロードを完了するには、すべての有効な partETags を提供する必要があります。OSS は、送信された partETags を受信した後、各パートを検証します。すべてのパートが検証されると、OSS はそれらを結合して完全なオブジェクトを作成します。
CompleteMultipartUploadRequest completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
// マルチパートアップロード中に同名のオブジェクトを上書きするかどうかを指定します。
// x-oss-forbid-overwrite を指定しない場合、デフォルトで同名のオブジェクトは上書きされます。
// x-oss-forbid-overwrite を false に設定すると、同名のオブジェクトは上書きされます。
// x-oss-forbid-overwrite を true に設定すると、同名のオブジェクトは上書きされません。同名のオブジェクトが既に存在する場合、プログラムはエラーを報告します。
completeMultipartUploadRequest.addHeader("x-oss-forbid-overwrite", "true");
// アップロードを完了します。
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}関連ドキュメント
さまざまなアップロードシナリオで同名オブジェクトの上書きを防止する方法を示す完全なサンプルコードについては、GitHub の例をご参照ください。
シンプルアップロードの API 操作の詳細については、「PutObject」をご参照ください。
オブジェクトのコピーの API 操作の詳細については、「CopyObject」をご参照ください。
マルチパートアップロードの API 操作の詳細については、「InitiateMultipartUpload」および「CompleteMultipartUpload」をご参照ください。