全部文档
当前文档

暂无内容

如果没有找到您期望的内容,请尝试其他搜索词

文档中心

分块上传(Java)

最近更新时间:2025-04-25 15:43:03

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

使用标准方式列举空间中正在进行的分块上传

public void listMultipartUploads() {
    // 初始化 Ks3Client,参见“初始化”文档
    Ks3Client ks3Client = initKs3Client();

    try {
        // 创建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
         */
        request.setDelimiter("/");
        request.setPrefix("prefix");
        // 最多返回100条记录,默认(最多)是1000
        request.setMaxUploads(100);
        // 发起 list 请求
        ListMultipartUploadsResult result = ks3Client.listMultipartUploads(request);
        // 如果 isTruncated 为 true,说明结果被截断。
        // 可以通过 nextKeyMarker 和 nextUploadIdMarker 作为下一次请求的 keyMarker 和 uploadIdMarker 继续请求
        System.out.println("Is Truncated: " + result.isTruncated());
        System.out.println("Next Key Marker: " + result.getNextKeyMarker());
        System.out.println("Next Upload ID Marker: " + result.getNextUploadIdMarker());
        System.out.println("Common Prefixes: " + result.getCommonPrefixes());
        System.out.println("Uploads: " + result.getUploads());
    } catch (Ks3ServiceException e) {
        System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
        System.out.println("Error Message: " + e.getErrorMessage());
        System.out.println("Error Code: " + e.getErrorCode());
        System.out.println("Request ID: " + e.getRequestId());
    } catch (Ks3ClientException e) {
        System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
        System.out.println("Error Message: " + e.getMessage());
    } finally {
        // 不再使用时,关闭 Ks3Client
        ks3Client.shutdown();
    }
}

1. 最多只能返回1000条记录。

2. keyMarker、uploadIdMarker、delimiter、prefix、maxUploads都不是必要参数。用户可以根据自己的实际情况调节。

3. 当返回的result.isTruncated()为true时,需要用返回的result.getNextKeyMarker()和result.getNextUploadIdMarker参数作为keyMarker和uploadIdMarker继续罗列之后的分块上传。

使用迭代器列举空间中正在进行的所有分块上传

public void listMultipartUploadsByIterator() {
    // 初始化 Ks3Client,参见“初始化”文档
    Ks3Client ks3Client = initKs3Client();

    try {
        // 创建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
         */
        request.setDelimiter("/");
        request.setPrefix("prefix");
        // 最多返回100条记录,默认(最多)是1000
        request.setMaxUploads(100);
        // 使用迭代器列举分块上传
        MultipartUploadListIterator iterator = ks3Client.newMultipartUploadListIterator(request);
        while (iterator.hasNext()) {
            ListMultipartUploadsResult result = iterator.next();
            System.out.println("Common Prefixes: " + result.getCommonPrefixes());
            System.out.println("Uploads: " + result.getUploads());
        }
    } catch (Ks3ServiceException e) {
        System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
        System.out.println("Error Message: " + e.getErrorMessage());
        System.out.println("Error Code: " + e.getErrorCode());
        System.out.println("Request ID: " + e.getRequestId());
    } catch (Ks3ClientException e) {
        System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
        System.out.println("Error Message: " + e.getMessage());
    } finally {
        // 不再使用时,关闭 Ks3Client
        ks3Client.shutdown();
    }
}

初始化分块上传

public void initMultipartUpload() {
    // 初始化 Ks3Client,参见“初始化”文档
    Ks3Client ks3Client = initKs3Client();

    try {
        // 初始化分块上传
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest("<your-bucket>", "<object-key>");
        // 设置存储类型
        request.setStorageClass(StorageClass.Standard);

        // 设置ACL
        request.setCannedAcl(CannedAccessControlList.Private);
        // 或者设置自定义ACL
        // AccessControlList accessControlList = new AccessControlList();
        // accessControlList.addGrant(new GranteeId("id"), Permission.Read);
        // request.setAcl(accessControlList);

        // 设置元数据
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType("text/plain");
        objectMetadata.setUserMeta("user-meta-key", "user-meta-value");
        request.setObjectMeta(objectMetadata);
        // 设置标签
        ObjectTagging objectTagging = new ObjectTagging();
        objectTagging.addObjectTag("key1", "value1");
        objectTagging.addObjectTag("key2", "value2");
        request.setObjectTagging(objectTagging);
        // 设置 KS3 托管密钥的服务端加密
        objectMetadata.setSseAlgorithm("AES256");
        // 或者设置客户提供密钥的服务端加密
        // request.setSseCustomerKey(getCustomerKey());

        // 设置是否禁止覆盖已有文件
        request.setForbidOverwrite(true);

        // 发起初始化分块上传请求
        InitiateMultipartUploadResult initResult = ks3Client.initiateMultipartUpload(request);
        String uploadId = initResult.getUploadId();
        System.out.println("Upload ID: " + uploadId);
    } catch (Ks3ServiceException e) {
        System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
        System.out.println("Error Message: " + e.getErrorMessage());
        System.out.println("Error Code: " + e.getErrorCode());
        System.out.println("Request ID: " + e.getRequestId());
    } catch (Ks3ClientException e) {
        System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
        System.out.println("Error Message: " + e.getMessage());
    } finally {
        // 不再使用时,关闭 Ks3Client
        ks3Client.shutdown();
    }
}

1. 通过result.getUploadId()可以获取到本次上传的uploadId,之后的操作中将到会用到该uploadId。

2. 如果用户使用了客户提供秘钥的服务端加密算法(SSE-C),则下载文件的时候,必须提供加密秘钥,否则将无法下载。

上传块

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

public void uploadPart() {
    // 初始化 Ks3Client,参见“初始化”文档
    Ks3Client ks3Client = initKs3Client();

    try {
        UploadPartRequest request = new UploadPartRequest("<your-bucket>", "<object-key>");
        // 设置分块上传 ID
        request.setUploadId("<upload-id>");
        // 设置分块号
        request.setPartNumber(1);
        // 设置分块大小,例:5MB
        request.setPartSize(5 * 1024 * 1024);
        // 设置文件及偏移量
        request.setFile(new File("<path-of-your-file>"));
        request.setFileoffset(0);
        // 或者上传 InputStream
        // byte[] data = "Hello, KS3!".getBytes();
        // request.setInputStream(new ByteArrayInputStream(data));
        // 使用 InputStream 时,分块大小需要设置为流的真实大小
        // request.setPartSize(data.length);

        PartETag partETag = ks3Client.uploadPart(request);
        System.out.println("Part Number: " + partETag.getPartNumber());
        System.out.println("Part Size: " + partETag.getPartSize());
        System.out.println("Part ETag: " + partETag.geteTag());
        System.out.println("Part CRC64: " + partETag.getCrc64Ecma());
    } catch (Ks3ServiceException e) {
        System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
        System.out.println("Error Message: " + e.getErrorMessage());
        System.out.println("Error Code: " + e.getErrorCode());
        System.out.println("Request ID: " + e.getRequestId());
    } catch (Ks3ClientException e) {
        System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
        System.out.println("Error Message: " + e.getMessage());
    } finally {
        // 不再使用时,关闭 Ks3Client
        ks3Client.shutdown();
    }
}

列举块

使用标准方式列举块

以下代码用于列举某个uploadId中已经上传的块:

public void listParts() {
    // 初始化 Ks3Client,参见“初始化”文档
    Ks3Client ks3Client = initKs3Client();

    try {
        // 创建 list 请求
        ListPartsRequest request = new ListPartsRequest("<your-bucket>", "<object-key>", "<upload-id>");
        // 设置最大返回的分块数,默认为 1000
        request.setMaxParts(100);
        // 设置分块号游标,将返回大于该分块号的分块
        request.setPartNumberMarker(0);
        // 发起 list 请求
        ListPartsResult listPartsResult = ks3Client.listParts(request);
        // 如果 isTruncated 为 true,说明结果被截断,可以通过 nextPartNumberMarker 作为下一次请求的 partNumberMarker 继续请求
        System.out.println("Is Truncated: " + listPartsResult.isTruncated());
        System.out.println("Next Part Number Marker: " + listPartsResult.getNextPartNumberMarker());
        System.out.println("Parts: " + listPartsResult.getParts());
    } catch (Ks3ServiceException e) {
        System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
        System.out.println("Error Message: " + e.getErrorMessage());
        System.out.println("Error Code: " + e.getErrorCode());
        System.out.println("Request ID: " + e.getRequestId());
    } catch (Ks3ClientException e) {
        System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
        System.out.println("Error Message: " + e.getMessage());
    } finally {
        // 不再使用时,关闭 Ks3Client
        ks3Client.shutdown();
    }
}

参数说明:

参数

说明

bucket

初始化分块上传时的bucket

key

初始化分块上传时的key

uploadId

初始化分块上传获取到的uploadId

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

使用迭代器列举所有块

public void listPartsByIterator() {
    // 初始化 Ks3Client,参见“初始化”文档
    Ks3Client ks3Client = initKs3Client();

    try {
        // 创建 list 请求
        ListPartsRequest request = new ListPartsRequest("<your-bucket>", "<object-key>", "<upload-id>");
        // 设置最大返回的分块数,默认为 1000
        request.setMaxParts(100);
        // 设置分块号游标,将返回大于该分块号的分块
        request.setPartNumberMarker(0);
        // 使用迭代器列举分块
        PartListIterator iterator = ks3Client.newPartListIterator(request);
        while (iterator.hasNext()) {
            ListPartsResult listPartsResult = iterator.next();
            System.out.println("Parts: " + listPartsResult.getParts());
        }
    } catch (Ks3ServiceException e) {
        System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
        System.out.println("Error Message: " + e.getErrorMessage());
        System.out.println("Error Code: " + e.getErrorCode());
        System.out.println("Request ID: " + e.getRequestId());
    } catch (Ks3ClientException e) {
        System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
        System.out.println("Error Message: " + e.getMessage());
    } finally {
        // 不再使用时,关闭 Ks3Client
        ks3Client.shutdown();
    }
}

完成分块上传

public void completeMultipartUpload() {
    // 初始化 Ks3Client,参见“初始化”文档
    Ks3Client ks3Client = initKs3Client();

    try {
        // 初始化分块 ETag 列表
        List<PartETag> partETagList = new ArrayList<>();
        //把上传块时返回的所有要合并的块依次添加进来
        // partETagList.add(...)
        // 初始化完成分块请求,设置 bucket,objectKey,uploadId,以及分块 ETag 列表
        CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest("<your-bucket>", "<object-key>", "<upload-id>", partETagList);
        // 设置禁止覆盖已有文件
        request.setForbidOverwrite(true);
        // 可以设置回调
        // 如果用户设置了回调,那么当文件即将上传成功时,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);
         */
        CompleteMultipartUploadResult result = ks3Client.completeMultipartUpload(request);
        System.out.println("ETag: " + result.geteTag());
        System.out.println("Crc64Ecma: " + result.getCrc64Ecma());
    } catch (Ks3ServiceException e) {
        System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
        System.out.println("Error Message: " + e.getErrorMessage());
        System.out.println("Error Code: " + e.getErrorCode());
        System.out.println("Request ID: " + e.getRequestId());
    } catch (Ks3ClientException e) {
        System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
        System.out.println("Error Message: " + e.getMessage());
    } finally {
        // 不再使用时,关闭 Ks3Client
        ks3Client.shutdown();
    }
}

取消分块上传

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

public void abortMultipartUpload() {
    // 初始化 Ks3Client,参见“初始化”文档
    Ks3Client ks3Client = initKs3Client();

    try {
        // 创建取消分块上传请求,设置 bucket,objectKey,uploadId
        AbortMultipartUploadRequest request = new AbortMultipartUploadRequest("<your-bucket>", "<object-key>", "<upload-id>");
        // 发起取消分块上传请求
        ks3Client.abortMultipartUpload(request);
        System.out.println("Abort multipart upload success.");
    } catch (Ks3ServiceException e) {
        System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
        System.out.println("Error Message: " + e.getErrorMessage());
        System.out.println("Error Code: " + e.getErrorCode());
        System.out.println("Request ID: " + e.getRequestId());
    } catch (Ks3ClientException e) {
        System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
        System.out.println("Error Message: " + e.getMessage());
    } finally {
        // 不再使用时,关闭 Ks3Client
        ks3Client.shutdown();
    }
}

分块上传完整流程

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

public void multipartUpload() {
    // 初始化 Ks3Client,参见“初始化”文档
    Ks3Client ks3Client = initKs3Client();

    try {
        // 创建InitiateMultipartUploadRequest对象。
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest("<your-bucket>", "<object-key>");
        // 设置禁止覆盖已有文件
        request.setForbidOverwrite(true);
        // 如果需要在初始化分片时设置文件存储类型,请参考以下示例代码。更多设置参见“初始化分块上传”
        // request.setStorageClass(StorageClass.StandardInfrequentAccess);
        // 初始化分片。
        InitiateMultipartUploadResult initResult = ks3Client.initiateMultipartUpload(request);
        // 返回uploadId,它是分片上传事件的唯一标识。您可以根据该 uploadId 发起相关的操作,例如取消分片上传、查询分片上传等。
        String uploadId = initResult.getUploadId();
        // partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
        List<PartETag> partETags = new ArrayList<>();
        // 每个分片的大小,用于计算文件有多少个分片。单位为字节。
        // 建议设置为5M(5*1024*1024)的整数倍,示例为 5MB。
        final long partSize = 5 * 1024 * 1024L;
        // 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
        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++) {
            PartETag partETag = uploadPart(ks3Client, uploadId, sampleFile, i + 1, partSize);
            partETags.add(partETag);
        }

        // 创建CompleteMultipartUploadRequest对象。
        // 在执行完成分片上传操作时,需要提供所有有效的partETags。
        // KS3收到提交的partETags后,会逐一验证每个分片的有效性。
        // 当所有的数据分片验证通过后,KS3将把这些分片组合成一个完整的文件。
        CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest("<your-bucket>", "<object-key>", uploadId, partETags);
        // 设置禁止覆盖已有文件
        completeRequest.setForbidOverwrite(true);
        // 完成上传。
        CompleteMultipartUploadResult completeMultipartUploadResult = ks3Client.completeMultipartUpload(completeRequest);
        System.out.println("ETag: " + completeMultipartUploadResult.geteTag());
        System.out.println("Crc64Ecma: " + completeMultipartUploadResult.getCrc64Ecma());
    } catch (IOException e) {
        System.out.println("IOException occurred, which means an I/O error occurred while trying to communicate with KS3.");
    } catch (Ks3ServiceException e) {
        System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
        System.out.println("Error Message: " + e.getErrorMessage());
        System.out.println("Error Code: " + e.getErrorCode());
        System.out.println("Request ID: " + e.getRequestId());
    } catch (Ks3ClientException e) {
        System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
        System.out.println("Error Message: " + e.getMessage());
    } finally {
        // 不再使用时,关闭 Ks3Client
        ks3Client.shutdown();
    }
}

private static PartETag uploadPart(Ks3Client ks3Client, String uploadId, File sampleFile, int partNum, long partSize) throws IOException {
    long startPos = (partNum - 1) * partSize;
    // 计算当前块的真实大小
    long fileLength = sampleFile.length();
    long curPartSize = Math.min(fileLength - startPos, partSize);
    try (InputStream inputStream = Files.newInputStream(sampleFile.toPath())) {
        // 跳过已经上传的分片。
        inputStream.skip(startPos);
        UploadPartRequest uploadPartRequest = new UploadPartRequest("<your-bucket>", "<object-key>");
        uploadPartRequest.setUploadId(uploadId);
        uploadPartRequest.setInputStream(inputStream);
        // 设置分块大小。
        // 除了最后一个块没有大小限制外,其余的块的大小均要求在100K以上。
        // 如果不符合上述要求,会返回413状态码。
        uploadPartRequest.setPartSize(curPartSize);
        // 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000.
        uploadPartRequest.setPartNumber(partNum);
        // 每次上传分片之后,KS3的返回结果包含PartETag。PartETag将被保存在partETags中。
        return ks3Client.uploadPart(uploadPartRequest);
    }
}

文档导读
纯净模式常规模式

纯净模式

点击可全屏预览文档内容
文档反馈