默认情况下,如果新添加文件(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。