預設情況下,如果新添加檔案(Object)與現有檔案同名且對該檔案有存取權限,則新添加的檔案將覆蓋原有的檔案。本文介紹如何通過佈建要求頭x-oss-forbid-overwrite在簡單上傳、拷貝檔案及分區上傳等情境中禁止覆蓋同名檔案。
注意事項
使用本文樣本前您需要先通過自訂網域名、STS等方式建立OSSClient,具體請參見如何初始化Android端OSSClient執行個體。
簡單上傳
以下代碼用於簡單上傳時禁止覆蓋同名檔案:
// 填寫Bucket名稱,例如examplebucket。關於Bucket名稱命名規範的更多資訊,請參見Bucket。
String bucketName = "examplebucket";
// 填寫不包含Bucket名稱在內的Object完整路徑,例如exampledir/exampleobject.txt。有關Object名稱命名規範的更多資訊,請參見Object。
String objectKey = "exampledir/exampleobject.txt";
// 填寫待上傳的本地檔案所在的完整路徑。
String localFile = "/storage/emulated/0/oss/examplefile.txt";
// 構造上傳請求。
PutObjectRequest put = new PutObjectRequest(bucketName, objectKey, localFile);
ObjectMetadata metadata = new ObjectMetadata();
// 指定上傳檔案操作時是否覆蓋同名Object。
// 不指定x-oss-forbid-overwrite時,預設覆蓋同名Object。
// 指定x-oss-forbid-overwrite為false時,表示允許覆蓋同名Object。
// 指定x-oss-forbid-overwrite為true時,表示禁止覆蓋同名Object,如果同名Object已存在,程式將報錯。
metadata.setHeader("x-oss-forbid-overwrite", "true");
put.setMetadata(metadata);
OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
Log.d("PutObject", "UploadSuccess");
Log.d("ETag", result.getETag());
Log.d("RequestId", result.getRequestId());
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
// 請求異常。
if (clientExcepion != null) {
// 用戶端異常,例如網路異常等。
clientExcepion.printStackTrace();
}
if (serviceException != null) {
// 服務端異常。
Log.e("ErrorCode", serviceException.getErrorCode());
Log.e("RequestId", serviceException.getRequestId());
Log.e("HostId", serviceException.getHostId());
Log.e("RawMessage", serviceException.getRawMessage());
}
}
});
拷貝檔案
以下代碼用於拷貝檔案時禁止覆蓋同名檔案:
// 填寫源Bucket名稱。
String srcBucketName = "srcbucket";
// 填寫源Bucket內的Object完整路徑。
String srcObjectKey = "dir1/srcobject.txt";
// 填寫目標Bucket名稱。
String destBucketName = "destbucket";
// 填寫目標Bucket內的Object完整路徑。
String destObjectKey = "dir2/destobject.txt";
// 建立Copy請求。
CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcObjectKey, destBucketName, destObjectKey);
ObjectMetadata metadata = new ObjectMetadata();
// 指定拷貝檔案操作時是否覆蓋同名Object。
// 不指定x-oss-forbid-overwrite時,預設覆蓋同名Object。
// 指定x-oss-forbid-overwrite為false時,表示允許覆蓋同名Object。
// 指定x-oss-forbid-overwrite為true時,表示禁止覆蓋同名Object,如果同名Object已存在,程式將報錯。
metadata.setHeader("x-oss-forbid-overwrite", "true");
copyObjectRequest.setNewObjectMetadata(metadata);
// 使用非同步方式拷貝檔案。
OSSAsyncTask copyTask = oss.asyncCopyObject(copyObjectRequest, new OSSCompletedCallback<CopyObjectRequest, CopyObjectResult>() {
@Override
public void onSuccess(CopyObjectRequest request, CopyObjectResult result) {
Log.d("copyObject", "copy success!");
}
@Override
public void onFailure(CopyObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
// 請求異常。
if (clientExcepion != null) {
// 用戶端異常,例如網路異常等。
clientExcepion.printStackTrace();
}
if (serviceException != null) {
// 服務異常。
Log.e("ErrorCode", serviceException.getErrorCode());
Log.e("RequestId", serviceException.getRequestId());
Log.e("HostId", serviceException.getHostId());
Log.e("RawMessage", serviceException.getRawMessage());
}
}
});
分區上傳
以下代碼用於分區上傳時禁止覆蓋同名檔案:
// 填寫Bucket名稱,例如examplebucket。
String bucketName = "examplebucket";
// 填寫不包含Bucket名稱在內的Object完整路徑,例如exampledir/exampleobject.txt。
String objectKey = "exampledir/exampleobject.txt";
// 填寫待上傳的本地檔案所在的完整路徑。
String localFile = "/storage/emulated/0/oss/examplefile.txt";
// 初始化分區上傳。
InitiateMultipartUploadRequest init = new InitiateMultipartUploadRequest(bucketName, objectKey);
ObjectMetadata metadata = new ObjectMetadata();
// 指定上傳檔案操作時是否覆蓋同名Object。
// 不指定x-oss-forbid-overwrite時,預設覆蓋同名Object。
// 指定x-oss-forbid-overwrite為false時,表示允許覆蓋同名Object。
// 指定x-oss-forbid-overwrite為true時,表示禁止覆蓋同名Object,如果同名Object已存在,程式將報錯。
metadata.setHeader("x-oss-forbid-overwrite", "true");
init.setMetadata(metadata);
InitiateMultipartUploadResult initResult = oss.initMultipartUpload(init);
// 返回uploadId。uploadId是分區上傳事件的唯一標識。您可以根據該uploadId發起相關操作,例如取消分區上傳、查詢分區上傳等。
String uploadId = initResult.getUploadId();
// 設定單個Part的大小,單位為位元組,取值範圍為100 KB~5 GB。
int partCount = 100 * 1024;
// 分區上傳。
List<PartETag> partETags = new ArrayList<PartETag>();
for (int i = 1; i < 5; i++) {
byte[] data = new byte[partCount];
RandomAccessFile raf = new RandomAccessFile(localFile, "r");
long skip = (i-1) * partCount;
raf.seek(skip);
raf.readFully(data, 0, partCount);
UploadPartRequest uploadPart = new UploadPartRequest();
uploadPart.setBucketName(bucketName);
uploadPart.setObjectKey(objectKey);
uploadPart.setUploadId(uploadId);
// 設定分區號,從1開始標識。每一個上傳的Part都有一個分區號,取值範圍是1~10000。
uploadPart.setPartNumber(i);
uploadPart.setPartContent(data);
try {
UploadPartResult result = oss.uploadPart(uploadPart);
PartETag partETag = new PartETag(uploadPart.getPartNumber(), result.getETag());
partETags.add(partETag);
} catch (ServiceException serviceException) {
OSSLog.logError(serviceException.getErrorCode());
}
}
Collections.sort(partETags, new Comparator<PartETag>() {
@Override
public int compare(PartETag lhs, PartETag rhs) {
if (lhs.getPartNumber() < rhs.getPartNumber()) {
return -1;
} else if (lhs.getPartNumber() > rhs.getPartNumber()) {
return 1;
} else {
return 0;
}
}
});
// 完成分區上傳。
CompleteMultipartUploadRequest complete = new CompleteMultipartUploadRequest(bucketName, objectKey, uploadId, partETags);
metadata = new ObjectMetadata();
// 指定完成上傳檔案操作時是否覆蓋同名Object。
// 不指定x-oss-forbid-overwrite時,預設覆蓋同名Object。
// 指定x-oss-forbid-overwrite為false時,表示允許覆蓋同名Object。
// 指定x-oss-forbid-overwrite為true時,表示禁止覆蓋同名Object,如果同名Object已存在,程式將報錯。
metadata.setHeader("x-oss-forbid-overwrite", "true");
complete.setMetadata(metadata);
CompleteMultipartUploadResult completeResult = oss.completeMultipartUpload(complete);
相關文檔
關於簡單上傳的API介面說明,請參見PutObject。
關於拷貝檔案的API介面說明,請參見CopyObject。
關於初始化OSSClient,請參見如何初始化Android端OSSClient執行個體。
分區上傳的完整實現涉及三個API介面,詳情如下:
關於初始化分區上傳事件的API介面說明,請參見InitiateMultipartUpload。
關於分區上傳Part的API介面說明,請參見UploadPart。
關於完成分區上傳的API介面說明,請參見CompleteMultipartUpload。