网站首页 > 技术文章 正文
直接上干货,分片上传需要完成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
- 最近发表
-
- count(*)、count1(1)、count(主键)、count(字段) 哪个更快?
- 深入探索 Spring Boot3 中 MyBatis 的 association 标签用法
- js异步操作 Promise fetch API 带来的网络请求变革—仙盟创梦IDE
- HTTP状态码超详细说明_http 状态码有哪些
- 聊聊跨域的原理与解决方法_跨域解决方案及原理
- 告别懵圈!产品新人的接口文档轻松入门指南
- 在Javaweb中实现发送简单邮件_java web发布
- 优化必备基础:Oracle中常见的三种表连接方式
- Oracle常用工具使用 - AWR_oracle工具有哪些
- 搭载USB 3.1接口:msi 微星 发布 990FXA Gaming 游戏主板
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)