OSS提供基于MD5和CRC64的数据校验,确保上传、下载和拷贝文件(Object)过程中的数据完整性。

MD5校验

如果上传文件时设置了Content-MD5,OSS会根据接收的内容计算MD5。OSS计算的MD5值和上传提供的MD5值不一致时,则返回InvalidDigest异常,从而保证数据的完整性。返回InvalidDigest异常后,您需要重新上传文件。

以下代码用于上传文件时进行MD5校验:

// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";

// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

// 上传字符串。
String content = "Hello OSS";

ObjectMetadata meta = new ObjectMetadata();
// 设置MD5校验。
String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5(content.getBytes()));
meta.setContentMD5(md5);

ossClient.putObject("<yourBucketName>", "<yourObjectName>", new ByteArrayInputStream(content.getBytes()), meta);

// 关闭OSSClient。
ossClient.shutdown();
说明 putObject、getObject、appendObject、postObject、uploadPart支持MD5校验。

CRC64校验

上传、下载和拷贝文件时默认开启CRC数据校验,确保数据的完整性。

说明
  • putObject、getObject、appendObject、uploadPart支持CRC64校验。上传时默认开启CRC校验,如果客户端计算的CRC值与服务端返回的CRC值不一致, 则会抛出InconsistentException异常。
  • 范围下载不支持CRC64校验。
  • CRC64校验会占用一定的CPU,对上传、下载速度均会有影响。
  • 下载文件时CRC64校验

    以下代码用于下载文件时进行CRC64数据完整性校验:

    // Endpoint以杭州为例,其它Region请按实际情况填写。
    String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
    // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
    String accessKeyId = "<yourAccessKeyId>";
    String accessKeySecret = "<yourAccessKeySecret>";
    String bucketName = "<yourBucketName>";
    String objectName = "<yourObjectName>";
    
    // 创建OSSClient实例。
    OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    
    // 流式下载。
    GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectName);
    OSSObject ossObject = ossClient.getObject(bucketName, objectName);
    
    // 读取文件内容,只有读取文件内容之后才能获取clientCrc。
    System.out.println("Object content:");
    BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
    while (true) {
        String line = reader.readLine();
        if (line == null) break;
    
        System.out.println("\n" + line);
    }
    // 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
    reader.close();
    
    // 查看客户端是否开启了crc校验,默认是开启状态。
    Boolean isCrcCheckEnabled = ((OSSClient)ossClient).getClientConfiguration().isCrcCheckEnabled();
    // 查看是否是范围下载请求。范围下载方式不支持校验crc。
    Boolean isRangGetRequest = getObjectRequest.getHeaders().get(OSSHeaders.RANGE) != null;
    
    // 校验crc,只有读取文件内容之后才能获取clientCrc。
    if (isCrcCheckEnabled && !isRangGetRequest) {
        Long clientCRC = IOUtils.getCRCValue(ossObject.getObjectContent());
        OSSUtils.checkChecksum(clientCRC, ossObject.getServerCRC(), ossObject.getRequestId());
    }
    
    // 关闭OSSClient。
    ossClient.shutdown();
  • 追加上传时CRC64校验
    // Endpoint以杭州为例,其它Region请按实际情况填写。
    String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
    // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
    String accessKeyId = "<yourAccessKeyId>";
    String accessKeySecret = "<yourAccessKeySecret>";
    String bucketName = "<yourBucketName>";
    String objectName = "<yourObjectName>";
    String firstAppendContent = "<yourFirstAppendContent>";
    String secondAppendContent = "<yourSecondAppendContent>";
    
    // 创建OSSClient实例。
    OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    
    // 第一次追加。
    AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucketName, objectName, new ByteArrayInputStream(firstAppendContent.getBytes()));
    appendObjectRequest.setPosition(0L);
    // 初始化crc。初始化crc之后,SDK内部默认会对上传结果进行crc校验。
    appendObjectRequest.setInitCRC(0L);
    AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
    
    // 第二次追加。
    appendObjectRequest = new AppendObjectRequest(bucketName, objectName, new ByteArrayInputStream(secondAppendContent.getBytes()));
    appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
    // 初始化crc设置为已上传数据的crc。初始化crc之后,SDK内部默认会对上传结果进行crc校验。
    appendObjectRequest.setInitCRC(appendObjectResult.getClientCRC());
    ossClient.appendObject(appendObjectRequest);
    
    // 关闭OSSClient。
    ossClient.shutdown();