网站首页 > 技术文章 正文
直接上干货,分片上传需要完成3步。
1.初始化分片上传。当此步骤成功完成之后,在存储桶(bucket)里便能搜到该文件,大小为 0 字节。需留意的是,应尽量避免对同一文件进行多次初始化操作。较为妥当的做法是,先终止前一次的初始化分片上传流程,再进行第二次的初始化分片上传工作。
private static String initialMultipartUpload(AmazonS3 oosClient) {
try {
// 必须设置BucketName和ObjectName
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(BUCKET_NAME, OBJECT_NAME);
// 设置存储类型,默认是标准存储,可不配置
request.setStorageClass(StorageClass.Standard);
// 设置元数据信息,例如设置数据的存放位置,可不配置
ObjectMetadata objectMetadata = new ObjectMetadata();
CtyunBucketDataLocation dataLocation = new CtyunBucketDataLocation();
ArrayList<String> location = new ArrayList<>();
// 设置数据存档的位置为青岛
location.add("QingDao");
dataLocation.setDataRegions(location);
// Allowed 允许调度 | NotAllowed 不允许调度, 可不配置
dataLocation.setStragegy(CtyunBucketDataLocation.CtyunBucketDataScheduleStrategy.Allowed);
objectMetadata.setDataLocation(dataLocation);
request.setObjectMetadata(objectMetadata);
InitiateMultipartUploadResult res = oosClient.initiateMultipartUpload(request);
String uploadID = res.getUploadId();
System.out.println("initialMultipartUpload success!" +
"\n" + "uploadID: " + uploadID);
return uploadID;
} catch (AmazonServiceException se) {
System.out.println(se.toString());
} catch (AmazonClientException ce) {
System.out.println(ce.getMessage());
}
return null;
}
2.上传分片。在初始化分片上传时,系统会返回一个上传标识(uploadId)。凭借此标识,便能够向存储桶内的大小为 0 字节的文件追加内容。需特别注意的是,每一个分片的大小必须大于 5MB,不过最后一个分片不受此限制。上传了多少内容,此时便能够通过对象存储下载相应字节数的内容。值得一提的是,此时存储桶里的文件在显示上依然为 0 字节,然而在下载时,文件已经包含了上传的内容。
* @param oosClient 初始化后的AmazonS3客户端
* @param uploadId 调用initiateMultipartUpload接口返回的uploadId
* @param currentPartNumber 当前上传的是第几片
* @param currentPartSize 当前上传片的大小 单位Byte
* @param parts 所有分片成功上传后返回的eTag值
* @param partNum 需要上传的分片总数
* @param offset 当前上传片的偏置 单位Byte
*/
private static void uploadPart(AmazonS3 oosClient, String uploadId, int currentPartNumber, long currentPartSize,
List<PartETag> parts, long partNum, long offset) {
try {
boolean isLastPart = currentPartNumber == partNum;
UploadPartRequest request = new UploadPartRequest().withUploadId(uploadId);
// 设置需要分片上传的文件
// 注意无需自行分片,直接设置需要分片上传的文件即可
request.setFile(UPLOAD_FILE);
// 设置BucketName
request.setBucketName(BUCKET_NAME);
// 设置ObjectName
request.setKey(OBJECT_NAME);
// 设置上传的是第几片
request.setPartNumber(currentPartNumber);
// 设置上传片的大小
request.setPartSize(currentPartSize);
// 如果不是第一个片,则需设置片的偏置
if (currentPartNumber != 1) {
request.setFileOffset(offset);
}
// 设置是否是最后一个片
request.setLastPart(isLastPart);
UploadPartResult res = oosClient.uploadPart(request);
System.out.println("uploadPart " + currentPartNumber + " success!");
String eTag = res.getPartETag().getETag();
System.out.println("eTag: " + eTag);
PartETag e = new PartETag(currentPartNumber, eTag);
parts.add(e);
System.out.println("The " + currentPartNumber + " part-> size: " + request.getPartSize() + " offset: " + request.getFileOffset());
} catch (AmazonServiceException se) {
System.out.println(se.toString());
} catch (AmazonClientException ce) {
System.out.println(ce.getMessage());
}
}
3.合并分片上传。此操作会依据上传标识(uploadId),结束该文件的分片上传通道,此后将无法继续向该文件追加内容。但在存储桶中,文件的大小已变实际大小。需要提醒的是,倘若你需要不定期地向文件追加内容,那么就不要进行合并分片操作。
* @param oosClient 初始化后的AmazonS3客户端
* @param uploadId 调用initiateMultipartUpload接口返回的uploadId
* @param parts 所有分片成功上传后返回的eTag值
*/
private static void completeMultipartUpload(AmazonS3 oosClient, String uploadId, List<PartETag> parts) {
try {
// 必须配置BucketName,ObjectName,初始化分片的uploadId和各个分片上传成功后返回的eTag值
CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest(BUCKET_NAME, OBJECT_NAME, uploadId, parts);
CompleteMultipartUploadResult result = oosClient.completeMultipartUpload(request);
System.out.println("complete multipart upload success!" +
"\n" + "location: " + result.getLocation());
System.out.printf("bucket:%s,obj:%s,etag:%s%n", result.getBucketName(), result.getKey(), result.getETag());
} catch (AmazonServiceException se) {
System.out.println(se.toString());
} catch (AmazonClientException ce) {
System.out.println(ce.getMessage());
}
}
4.主函数和Client
public static void main(String[] args) {
AmazonS3 client = getClient();
// 初始化分片上传
String uploadId = initialMultipartUpload(client);
// 终止分片上传
//abortMultipartUpload(client, uploadId);
// 分片大小(5MB)
long partSize = 5 * 1024 * 1024;
// 总分片数量
long PartNum = 3;
// 存储每个分片的 ETag
List<PartETag> partETags = new ArrayList<>();
// 上传第一个分片
long firstPartOffset = 0;
uploadPart(client, uploadId, 1, partSize, partETags, PartNum, firstPartOffset);
// 上传第二个分片
long secondPartOffset = partSize;
uploadPart(client, uploadId, 2, partSize, partETags, PartNum, secondPartOffset);
// 上传第三个分片
long thirdPartOffset = 2 * partSize;
long thirdPartSize = UPLOAD_FILE.length() - thirdPartOffset;
uploadPart(client, uploadId, 3, thirdPartSize, partETags, PartNum, thirdPartOffset);
// 完成分片上传
completeMultipartUpload(client, uploadId, partETags);
}
private static AmazonS3 getClient() {
ClientConfiguration cc = new ClientConfiguration();
cc.setMaxErrorRetry(3);
cc.setConnectionTimeout(30000);
cc.setSocketTimeout(30000);
cc.setProtocol(Protocol.HTTP);
//设置path-style方式,如oos-cn.ctyunapi.cn/bucket.example
//S3ClientOptions options = new S3ClientOptions();
//options.setPathStyleAccess(true);
//支持的最大并发连接数
cc.setMaxConnections(100);
// 是否使用v4
System.setProperty(SDKGlobalConfiguration.ENABLE_S3_SIGV4_SYSTEM_PROPERTY, "true");
AmazonS3 client = new AmazonS3Client(new AWSCredentials() {
@Override
public String getAWSAccessKeyId() {
return TestConfig.OOS_ACCESS_KEY;
}
@Override
public String getAWSSecretKey() {
return TestConfig.OOS_SECRET_KEY;
}
}, cc);
client.setEndpoint(TestConfig.OOS_ENDPOINT);
//设置path-style方式,如oos-cn.ctyunapi.cn/bucket.example
//client.setS3ClientOptions(options);
return client;
}
oos-java-sdk下载地址:
https://www.ctyun.cn/document/10026693/10026825
猜你喜欢
- 2025-07-09 视图计算背后的技术架构思考(实验4.2视图的使用)
- 2025-07-09 自己动手从0开始实现一个分布式 RPC 框架
- 2025-07-09 阿里开源MySQL中间件Canal快速入门
- 2025-07-09 网络也会堵车?!有3大法宝可以搞定它!
- 2025-07-09 终于把TCP/IP 协议讲的明明白白了,再也不怕被问三次握手了
- 2025-07-09 36 张图带你理解计算机网络 6 大基础知识点
- 2025-07-09 别再裸写 parseFrom() 了!这才是 MQTT + Protobuf 消费的正确姿势
- 2025-07-09 非常强悍的 RabbitMQ 总结,写得真好
- 2025-07-09 部署canal server 1.1.5,消费mysql信息,订阅测试
- 2025-07-09 再聊HttpClient的NoHttpResponseException
- 1509℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 533℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 496℃MySQL service启动脚本浅析(r12笔记第59天)
- 475℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 473℃启用MySQL查询缓存(mysql8.0查询缓存)
- 453℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 432℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 430℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)