全部文档
当前文档

暂无内容

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

文档中心

复制文件(Java)

最近更新时间:2025-03-06 10:34:56

1. 普通复制文件

1. 该方式支持复制5GB及以下的文件,如需复制5GB以上的文件,请使用分块复制方式。
3. 鉴于性能考虑,推荐您在复制1G以上的文件时采用分块复制方式。
4. 仅支持桶内复制或同Region跨桶复制,不支持跨Region复制。

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

    try {
        // 创建copy请求,将sourceBucket这个存储空间下的sourceKey这个object复制到destinationBucket这个存储空间下,并命名为destinationObject
        CopyObjectRequest request = new CopyObjectRequest("destinationBucket", "destinationObject", "sourceBucket", "sourceKey");

        // 设置新文件的ACL
        request.setCannedAcl(CannedAccessControlList.Private);
        // 或者指定用户的权限
        AccessControlList acl = new AccessControlList();
        acl.addGrant(new GranteeId("<user-id>"), Permission.Read);
        acl.addGrant(new GranteeEmail("<user-email>"), Permission.Write);
        request.setAccessControlList(acl);

        // 设置新文件的存储类型
        request.setStorageClass(StorageClass.Standard);

        // 设置新文件的元数据
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType("text/plain");
        objectMetadata.setUserMeta("key1", "value1");
        // 设置新文件的元数据指令,REPLACE 表示替换,COPY 表示保留原有元数据
        objectMetadata.setHeader(HttpHeaders.XKssMetadataDirective.toString(), "REPLACE");
        // 设置新文件的标签指令,REPLACE 表示替换,COPY 表示保留原有标签
        objectMetadata.setHeader(HttpHeaders.XKssTaggingDirective.toString(), "REPLACE");
        request.setNewObjectMetadata(objectMetadata);

        // 设置新文件的标签
        ObjectTagging objectTagging = new ObjectTagging();
        objectTagging.addObjectTag("key1", "value1");
        request.setObjectTagging(objectTagging);

        // 如果目的文件已存在,是否覆盖,true:不覆盖,false:覆盖
        request.setForbidOverwrite(true);

        /*
         * 可以指定目的文件的加密方式
         * 1. 服务端加密
         * 2. 用户提供key的方式进行服务端解密,并设置新的文件的服务端加密
         */

        // 1. copy 后的文件以服务端加密方式存储
        // ObjectMetadata meta = new ObjectMetadata();
        // meta.setSseAlgorithm("AES256");
        // request.setNewObjectMetadata(meta);


        // 2. copy的文件以用户提供key的方式进行服务端解密,并设置新的文件的服务端加密
        // 生成一个密钥,这个密钥需要自己保存好,加密解密都需要
        // KeyGenerator symKeyGenerator = KeyGenerator.getInstance("AES");
        // symKeyGenerator.init(256);
        // SecretKey destKey= symKeyGenerator.generateKey();
        // SecretKey sourceKey= ??//当初加密时用的key
        // 指定被拷贝的数据是用sourceKey进行加密的,拷贝时将用该key先对数据解密
        // request.setSourceSSECustomerKey(new SSECustomerKey(sourceKey));
        // 指定拷贝生成的新数据的加密方式
        // request.setDestinationSSECustomerKey(new SSECustomerKey(destKey));
        // 发起copy请求
        ks3Client.copyObject(request);
    } 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();
    }
}

2. 分块复制文件

1. 该方式支持复制任意大小的文件。
2. 鉴于性能考虑,推荐您在复制1GB以上的文件时采用分块复制方式。
3. 仅支持桶内复制或同Region跨桶复制,不支持跨Region复制。

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

    try {
        // 初始化分块复制
        InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest("dsBucketName", "dstObjectKey");

        // 设置新文件的元数据,该方式不支持通过指定 x-kss-metadata-directive 请求头来指定元数据的处理方式
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType("text/plain");
        objectMetadata.setUserMeta("key1", "value1");
        initRequest.setObjectMeta(objectMetadata);

        // 设置新文件的 ACL
        initRequest.setCannedAcl(CannedAccessControlList.Private);
        // 或者指定用户的权限
        AccessControlList acl = new AccessControlList();
        acl.addGrant(new GranteeId("<user-id>"), Permission.Read);
        acl.addGrant(new GranteeEmail("<user-email>"), Permission.Write);
        initRequest.setAcl(acl);

        // 设置新文件的存储类型
        initRequest.setStorageClass(StorageClass.Standard);

        // 设置新文件的标签
        initRequest.addObjectTag("key1", "value1");

        // 加密方式:服务端加密
        initRequest.getObjectMeta().setHeader(HttpHeaders.XKssServerSideEncryption.toString(), "AES256");

        // 加密方式:用户提供key的方式进行服务端加密
        // 生成一个秘钥,这个秘钥需要自己保存好,加密解密都需要
//        KeyGenerator symKeyGenerator = KeyGenerator.getInstance("AES");
//        symKeyGenerator.init(256);
//        SecretKey secretKey = symKeyGenerator.generateKey();
//        // 将 key 保存到文件中
//        byte[] encoded = secretKey.getEncoded();
//        Files.write(Paths.get("secretKey"), encoded);
//        SSECustomerKey sseCustomerKey = new SSECustomerKey(secretKey);
//        initRequest.setSseCustomerKey(sseCustomerKey);

        // 如果目的文件已存在,是否覆盖,true:不覆盖,false:覆盖
        initRequest.setForbidOverwrite(true);

        // 发起初始化分块复制请求
        InitiateMultipartUploadResult initiateMultipartUploadResult = ks3Client.initiateMultipartUpload(initRequest);
        // 获取 uploadId
        // uploadId 表示分块复制任务的唯一 ID,用于后续操作,如上传文件块、完成分块上传等
        String uploadId = initiateMultipartUploadResult.getUploadId();

        // 获取源文件大小
        HeadObjectResult headObjectResult = ks3Client.headObject("srcBucketName", "srcObjectKey");
        long fileSize = headObjectResult.getObjectMetadata().getContentLength();

        // 分片大小。
        // 除了最后一个块没有大小限制外,其余的块的大小均要求在100K以上。推荐分片大小为 5M 的整数倍,如:100M。
        // 如果不符合上述要求,会返回413状态码。
        long partSize = 100 * 1024 * 1024; // 100M
        // 计算总共需要分多少块
        long totalParts = fileSize / partSize;
        if (fileSize % partSize != 0) {
            totalParts++;
        }

        List<PartETag> partETags = new ArrayList<>();
        // 分块复制文件
        for (int i = 0; i < totalParts; i++) {
            // 分片号。每一个上传的分片都有一个分片号,取值范围是1~10000.
            int partNum = i + 1;
            CopyPartRequest copyPartRequest = new CopyPartRequest("srcBucketName", "srcObjectKey", "dstBucketName", "dstObjectKey", partNum, uploadId);
            // 设置该块的起始、结束位置
            long startIndex = i * partSize;
            long endIndex = startIndex + partSize - 1;
            if (endIndex >= fileSize) {
                endIndex = fileSize - 1;
            }
            copyPartRequest.setBeginRange(startIndex);
            copyPartRequest.setEndRange(endIndex);
            // 如果源 object 使用客户提供的 key 加密,则需要提供
//            copyPartRequest.setSourceSSECustomerKey(srcKey);
            // 如果目标 object 使用客户提供的 key 加密,则需要提供
//            copyPartRequest.setDestinationSSECustomerKey(dstKey);
            CopyResult copyResult = ks3Client.copyPart(copyPartRequest);
            // 每次上传分片之后,保存返回结果中的 PartETag,用于合并分块。
            partETags.add(new PartETag(partNum, copyResult.getETag()));
        }

        // 完成分块上传
        // 在执行完成分片上传操作时,需要提供所有有效的 partETags。
        // KS3收到提交的partETags后,会逐一验证每个分片的有效性。
        // 当所有的数据分片验证通过后,KS3将把这些分片组合成一个完整的文件。
        CompleteMultipartUploadResult completeMultipartUploadResult = ks3Client.completeMultipartUpload("dstBucketName", "dstObjectKey", uploadId, partETags);
        System.out.println(completeMultipartUploadResult.geteTag());
    } 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. 文件复制时,需要用户对源文件有读取权限,对目标桶有写入权限。

2. 如果目标文件已经存在,且设置了禁止覆盖同名文件(默认),复制操作将会抛出400,对应的ErrorCode为invalidKey

纯净模式常规模式

纯净模式

点击可全屏预览文档内容