分块上传(JAVA)

最近更新时间:2022-11-09 17:09:26

分块上传相关

分块上传流程:

  1. 初始化分块上传
  2. 多次调用上传块
  3. 完成分块上传

罗列空间中正在进行的分块上传

public ListMultipartUploadsResult listMultipartUploads() {
       // yourEndpoint填写Bucket所在地域对应的Endpoint。以中国(北京)为例,Endpoint填写为ks3-cn-beijing.ksyuncs.com。如果使用自定义域名,设置endpoint为自定义域名,同时设置domainMode为true
       String endpoint = "yourEndpoint";
       // 金山云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用子账号账号进行 API 访问或日常运维,请登录 https://uc.console.ksyun.com/pro/iam/#/user/list 创建子账号。
       String accessKeyId = "yourAccessKeyId";
       String accessKeySecret = "yourAccessKeySecret";
       // 创建Ks3ClientConfig 实例。
       Ks3ClientConfig config = new Ks3ClientConfig();
       // 设置域名
       config.setEndpoint(endpoint);
       /**
        * false: (推荐)使用三级域名:{bucketName}.{endpoint}/{objectKey}的形式访问
        * true:  使用二级域名:{endpoint}/{bucketName}/{objectKey}的形式访问
        * 如果domainMode设置为true,则pathStyleAccess可忽略设置
        */
       config.setPathStyleAccess(false);

       // 创建Ks3Client实例
       Ks3 client = new Ks3Client(accessKeyId, accessKeySecret, config);
       // 创建list请求,获取 example桶的分块列表。
       ListMultipartUploadsRequest request = new ListMultipartUploadsRequest("example");
       /**
        * keyMarker为空,uploadIdMarker不为空
        * 无意义
        * 
        * keyMarker不为空,uploadIdMarker不为空
        * 列出分块上传object key为keyMarker,且upload id 字典排序大于uploadIdMarker的结果
        * 
        * keyMarker不为空,uploadIdMarker为空
        * 列出分块上传object key字典排序大于keyMarker的结果
        */
        request.setKeyMarker("keyMarker");
        request.setUploadIdMarker("uploadIdMarker");

        /**
        * prefix和delimiter详解
        *
        * commonPrefix由prefix和delimiter确定,以prefix开头的object
        * key,在prefix之后首次出现delimiter的位置之前(包含delimiter)的子字符串将存在于commonPrefixes中
        * 比如有以下几个分块上传
        * 
        * aaaa/bbb/ddd.txt
        * aaaa/ccc/eee.txt
        * ssss/eee/fff.txt
        * prefix为空 delimiter为/ 
        * 则commonPrefix 为 aaaa/和ssss/ 返回的uploads为空
        * 
        * prefix为aaaa/ delimiter为/ 
        * 则commonPrefix 为 aaaa/bbb/和aaaa/ccc/ 返回的uploads为空
        * 
        * prefix为ssss/ delimiter为/ 
        * 则commonPrefix 为 aaaa/eee/ 返回的uploads为空
        * 
        * prefix为空 delimiter为空 
        * 则commonPrefix 为空 返回的uploads为aaaa/bbb/ddd.txt、aaaa/ccc/eee.txt、ssss/eee/fff.txt
        * 
        * prefix为aaaa/ delimiter为空 
        * 则commonPrefix 为空 返回的uploads为aaaa/bbb/ddd.txt、aaaa/ccc/eee.txt
        * 
        * prefix为ssss/ delimiter为空 
        * 则commonPrefix 为空 返回的uploads为ssss/eee/fff.txt
        * </p>
        */
       request.setDelimiter("/");
       request.setPrefix("prefix");
       request.setMaxUploads(100);// 最多返回100条记录,默认(最多)是1000
       ListMultipartUploadsResult result = client.listMultipartUploads(request);
       return result;
}

说明:

  • 最多只能返回1000条记录。
  • keyMarker、uploadIdMarker、delimiter、prefix、maxUploads都不是必要参数。用户可以根据自己的实际情况调节。
  • 当返回的result.isTruncated()为true时,需要用返回的result.getNextKeyMarker()和result.getNextUploadIdMarker参数作为keyMarker和uploadIdMarker继续罗列之后的分块上传。

初始化分块上传

public InitiateMultipartUploadResult initMultipartUpload(){
       // yourEndpoint填写Bucket所在地域对应的Endpoint。以中国(北京)为例,Endpoint填写为ks3-cn-beijing.ksyuncs.com。如果使用自定义域名,设置endpoint为自定义域名,同时设置domainMode为true
       String endpoint = "yourEndpoint";
       // 金山云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用子账号账号进行 API 访问或日常运维,请登录 https://uc.console.ksyun.com/pro/iam/#/user/list 创建子账号。
       String accessKeyId = "yourAccessKeyId";
       String accessKeySecret = "yourAccessKeySecret";
       // 创建Ks3ClientConfig 实例。
       Ks3ClientConfig config = new Ks3ClientConfig();
       // 设置域名
       config.setEndpoint(endpoint);
       /**
        * false: (推荐)使用三级域名:{bucketName}.{endpoint}/{objectKey}的形式访问
        * true:  使用二级域名:{endpoint}/{bucketName}/{objectKey}的形式访问
        * 如果domainMode设置为true,则pathStyleAccess可忽略设置
        */
       config.setPathStyleAccess(false);

       // 创建Ks3Client实例
       Ks3 client = new Ks3Client(accessKeyId, accessKeySecret, config);
       // 创建分块上传任务,桶为example, 文件名为 exampleobject;
       InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest("example", "exampleobject");
       // 设置为公开读
       request.setCannedAcl(CannedAccessControlList.PublicRead);
       // 初始化分块上传时设置元数据
       // 设置将要上传的object的用户元数据。当下载文件的时候,返回的header中将会带上设置的用户元数据。
       // meta.setUserMeta("x-kss-meta-example", "example");
       // 设置将要上传的object的元数据。
       // 如果用户设置了Content-Type,那么在下载的时候,返回的header中将会带上Content-Type:{设置的值} 。建议根据文件实际类型做相应设置,方便浏览器识别。
       // meta.setContentType("text/html");


       // 设置服务端加密
       // meta.setSseAlgorithm("AES256");

       // 设置用提供key的服务端加密
       /**
        * KeyGenerator symKeyGenerator = KeyGenerator.getInstance("AES");
        * symKeyGenerator.init(256); 
        * SecretKey symKey = symKeyGenerator.generateKey();
        * SSECustomerKey ssec = new SSECustomerKey(symKey);
        * request.setSseCustomerKey(ssec);
        */

       // 请求设置meta
       // request.setObjectMeta(meta);
       // 发起请求
       InitiateMultipartUploadResult result = client.initiateMultipartUpload(request);
       // 获取初始化的uploadId,之后的操作中将会用到。
       result.getUploadId();
       return result;
}

说明:

  • 通过result.getUploadId()可以获取到本次上传的uploadId,之后的操作中将到会用到该uploadId。
  • 如何下载文件?详见6.7和6.8。
  • 如果用户使用了用户提供key的服务端加密,则下载文件的时候,必须提供加密使用的key,否则将无法下载。

上传块

提供文件及partSize和offset参数的方式上传。

public PartETag uploadPart(){
       // yourEndpoint填写Bucket所在地域对应的Endpoint。以中国(北京)为例,Endpoint填写为ks3-cn-beijing.ksyuncs.com。如果使用自定义域名,设置endpoint为自定义域名,同时设置domainMode为true
       String endpoint = "yourEndpoint";
       // 金山云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用子账号账号进行 API 访问或日常运维,请登录 https://uc.console.ksyun.com/pro/iam/#/user/list 创建子账号。
       String accessKeyId = "yourAccessKeyId";
       String accessKeySecret = "yourAccessKeySecret";
       // 创建Ks3ClientConfig 实例。
       Ks3ClientConfig config = new Ks3ClientConfig();
       // 设置域名
       config.setEndpoint(endpoint);
       /**
        * false: (推荐)使用三级域名:{bucketName}.{endpoint}/{objectKey}的形式访问
        * true:  使用二级域名:{endpoint}/{bucketName}/{objectKey}的形式访问
        * 如果domainMode设置为true,则pathStyleAccess可忽略设置
        */
       config.setPathStyleAccess(false);

       // 创建Ks3Client实例
       Ks3 client = new Ks3Client(accessKeyId, accessKeySecret, config);
       // 需要上传的文件
       File file = new File("D:\\localpath\\examplefile.txt");
       // 创建上传分块任务的请求,传入 bucket名字,object名字,初始化分块任务得到的uploadId, 分块序号【1,10000】。 要上传的文件,分块的大小以及文件的偏移量、
       UploadPartRequest request = new UploadPartRequest({bucket}, {key} ,{uploadId},{partNumber},file, {partSize},{offset});
       //可以指定内容的MD5值,否则程序只会在客户端进行MD5校验。如果指定的话会在服务端进行MD5校验
       //request.setContentMd5("yE0ZQBpRgPrLSDEe6fGAvg==");
       PartETag result = client.uploadPart(request);
       return result;
}

罗列已经上传的块

罗列一个uploadId已经上传的块。

public ListPartsResult listParts(){
       // yourEndpoint填写Bucket所在地域对应的Endpoint。以中国(北京)为例,Endpoint填写为ks3-cn-beijing.ksyuncs.com。如果使用自定义域名,设置endpoint为自定义域名,同时设置domainMode为true
       String endpoint = "yourEndpoint";
       // 金山云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用子账号账号进行 API 访问或日常运维,请登录 https://uc.console.ksyun.com/pro/iam/#/user/list 创建子账号。
       String accessKeyId = "yourAccessKeyId";
       String accessKeySecret = "yourAccessKeySecret";
       // 创建Ks3ClientConfig 实例。
       Ks3ClientConfig config = new Ks3ClientConfig();
       // 设置域名
       config.setEndpoint(endpoint);
       /**
        * false: (推荐)使用三级域名:{bucketName}.{endpoint}/{objectKey}的形式访问
        * true:  使用二级域名:{endpoint}/{bucketName}/{objectKey}的形式访问
        * 如果domainMode设置为true,则pathStyleAccess可忽略设置
        */
       config.setPathStyleAccess(false);

       // 创建Ks3Client实例
       Ks3 client = new Ks3Client(accessKeyId, accessKeySecret, config);
       // 创建罗列已经上传的块请求传入桶名,文件名已经uploadId
       ListPartsRequest request = new ListPartsRequest("example", "exampleobject" ,"{uploadId}");
       ListPartsResult tags = client.listParts(request);
       return tags;
}

参数说明:

  • bucket:初始化分块上传时的bucket。
  • key:初始化分块上传时的key。
  • uploadId:初始化分块上传获取到的uploadId。

说明:

  • 该接口最多只会返回1000条记录,如果总数大于1000,请使用request.setPartNumberMarker()方法设置partNumber的起始位置。

完成分块上传

public void completaMultipartUpload(){
       // yourEndpoint填写Bucket所在地域对应的Endpoint。以中国(北京)为例,Endpoint填写为ks3-cn-beijing.ksyuncs.com。如果使用自定义域名,设置endpoint为自定义域名,同时设置domainMode为true
       String endpoint = "yourEndpoint";
       // 金山云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用子账号账号进行 API 访问或日常运维,请登录 https://uc.console.ksyun.com/pro/iam/#/user/list 创建子账号。
       String accessKeyId = "yourAccessKeyId";
       String accessKeySecret = "yourAccessKeySecret";
       // 创建Ks3ClientConfig 实例。
       Ks3ClientConfig config = new Ks3ClientConfig();
       // 设置域名
       config.setEndpoint(endpoint);
       /**
        * false: (推荐)使用三级域名:{bucketName}.{endpoint}/{objectKey}的形式访问
        * true:  使用二级域名:{endpoint}/{bucketName}/{objectKey}的形式访问
        * 如果domainMode设置为true,则pathStyleAccess可忽略设置
        */
       config.setPathStyleAccess(false);

       // 创建Ks3Client实例
       Ks3 client = new Ks3Client(accessKeyId, accessKeySecret, config);
       List<PartETag> parts = new ArrayList<PartETag>();
       //把上传块时返回的所有要合并的块依次添加进来
       //parts.add(...)
       // 创建分块上传完成请求,需要传入桶名、文件名、uploadId, 分块列表。
       CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest({bucket},{key},{uploadId}, parts);

       // 可以设置回调
       /**
        * //如果用户设置了回调,那么当文件即将上传成功时,KS3将会使用POST的方式调用用户提供的回调地址,如果调用成功且用户处理成功(用户处理成功指返回{"result":true}给KS3,处理失败返回{"result":false}),那么文件才会真正的上传成功,如果调用失败或者用户处理失败,那么文件最终会上传失败。用户可以设置KS3回调时的body,最后KS3将会把用户提供的参数组织成json格式返回给用户。在下面示例中,KS3回调时的body为{"bucket":<实际存储的bucket>,"createTime":<文件创建时间>,"etag":<文件的etag,即文件的MD5经hex处理后的值>,"key":<文件实际保持的key>,"mimType":<文件的Content-Type>,"objectSize":<文件的字节数大小>,"time":"20150222"}
        * CallBackConfiguration config = new CallBackConfiguration();
        * config.setCallBackUrl("http://10.4.2.38:19090/");//KS3服务器回调的地址
        * //以下为KS3服务器访问http://10.4.2.38:19090/时body中的参数
        * Map<String,MagicVariables> magicVariables = new HashMap<String,MagicVariables>();
        * magicVariables.put("bucket", MagicVariables.bucket);
        * magicVariables.put("createTime", MagicVariables.createTime);
        * magicVariables.put("etag", MagicVariables.etag);
        * magicVariables.put("key", MagicVariables.key);
        * magicVariables.put("mimeType", MagicVariables.mimeType);
        * magicVariables.put("objectSize", MagicVariables.objectSize);
        * config.setBodyMagicVariables(magicVariables);
        * //用户可以自己定义返回的参数。
        * Map<String,String> kssVariables = new HashMap<String,String>();
        * kssVariables.put("time", "20150222");
        * request.setCallBackConfiguration(config);
        */
       client.completeMultipartUpload(request);
}

取消分块上传

对于不再使用的分块上传,建议调用该接口取消。

public void abortMultipartUpload(){
       // yourEndpoint填写Bucket所在地域对应的Endpoint。以中国(北京)为例,Endpoint填写为ks3-cn-beijing.ksyuncs.com。如果使用自定义域名,设置endpoint为自定义域名,同时设置domainMode为true
       String endpoint = "yourEndpoint";
       // 金山云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用子账号账号进行 API 访问或日常运维,请登录 https://uc.console.ksyun.com/pro/iam/#/user/list 创建子账号。
       String accessKeyId = "yourAccessKeyId";
       String accessKeySecret = "yourAccessKeySecret";
       // 创建Ks3ClientConfig 实例。
       Ks3ClientConfig config = new Ks3ClientConfig();
       // 设置域名
       config.setEndpoint(endpoint);
       /**
        * false: (推荐)使用三级域名:{bucketName}.{endpoint}/{objectKey}的形式访问
        * true:  使用二级域名:{endpoint}/{bucketName}/{objectKey}的形式访问
        * 如果domainMode设置为true,则pathStyleAccess可忽略设置
        */
       config.setPathStyleAccess(false);

       // 创建Ks3Client实例
       Ks3 client = new Ks3Client(accessKeyId, accessKeySecret, config);
       // 放弃分块上传任务,传入桶名,文件名以及uploadId.
       client.abortMultipartUpload(bucketname, objectkey, uploadId);
}

分块上传完整流程

以下通过一个完整的示例对分片上传的流程进行逐步解析:

         // yourEndpoint填写Bucket所在地域对应的Endpoint。以中国(北京)为例,Endpoint填写为ks3-cn-beijing.ksyuncs.com。如果使用自定义域名,设置endpoint为自定义域名,同时设置domainMode为true
        String endpoint = "yourEndpoint";
        // 金山云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用子账号账号进行 API 访问或日常运维,请登录 https://uc.console.ksyun.com/pro/iam/#/user/list 创建子账号。
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
        String objectName = "exampledir/exampleobject.txt";
        // 创建Ks3ClientConfig 实例。
        Ks3ClientConfig config = new Ks3ClientConfig();
        // 设置域名
        config.setEndpoint(endpoint);
       /**
        * false: (推荐)使用三级域名:{bucketName}.{endpoint}/{objectKey}的形式访问
        * true:  使用二级域名:{endpoint}/{bucketName}/{objectKey}的形式访问
        * 如果domainMode设置为true,则pathStyleAccess可忽略设置
        */
       config.setPathStyleAccess(false);

        // 创建Ks3Client实例
        Ks3 client = new Ks3Client(accessKeyId, accessKeySecret, config);
        // 创建InitiateMultipartUploadRequest对象。
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
        // 如果需要在初始化分片时设置文件存储类型,请参考以下示例代码。
        // request.setStorageClass(StorageClass.StandardInfrequentAccess);
        // 初始化分片。
        InitiateMultipartUploadResult upresult = client.initiateMultipartUpload(request);
        // 返回uploadId,它是分片上传事件的唯一标识。您可以根据该uploadId发起相关的操作,例如取消分片上传、查询分片上传等。
        String uploadId = upresult.getUploadId();
        // partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
        List<PartETag> partETags =  new ArrayList<PartETag>();
        // 每个分片的大小,用于计算文件有多少个分片。单位为字节。
        final long partSize = 1024 * 1024L;   //1 MB。
        // 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
        final File sampleFile = new File("D:\\localpath\\examplefile.txt");
        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(bucketName, objectName);
            uploadPartRequest.setUploadId(uploadId);
            uploadPartRequest.setInputStream(instream);
            // 设置分片大小。当所有块总大小大于5M时,除了最后一个块没有大小限制外,其余的块的大小均要求在5MB以上。当所有块总大小小于5M时,除了最后一个块没有大小限制外,其余的块的大小均要求在100K以上。如果不符合上述要求,会返回413状态码。
            uploadPartRequest.setPartSize(curPartSize);
            // 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000.
            uploadPartRequest.setPartNumber( i + 1);
            // 每次上传分片之后,KS3的返回结果包含PartETag。PartETag将被保存在partETags中。
            partETags.add(client.uploadPart(uploadPartRequest));
        }


        // 创建CompleteMultipartUploadRequest对象。
        // 在执行完成分片上传操作时,需要提供所有有效的partETags。KS3收到提交的partETags后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,KS3将把这些分片组合成一个完整的文件。
        CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
        // 完成上传。
        CompleteMultipartUploadResult completeMultipartUploadResult = client.completeMultipartUpload(completeMultipartUploadRequest);
        System.out.println(completeMultipartUploadResult.geteTag());

文档内容是否对您有帮助?

根本没帮助
文档较差
文档一般
文档不错
文档很好

在文档使用中是否遇到以下问题

内容不全,不深入
内容更新不及时
描述不清晰,比较混乱
系统或功能太复杂,缺乏足够的引导
内容冗长

更多建议

0/200

评价建议不能为空

提交成功!

非常感谢您的反馈,我们会继续努力做到更好!

问题反馈