获取错误请求400错误尝试使用生成的MD5或CRC32C校验和将文件上载到Google云存储

时间:2017-12-27 00:30:10

标签: google-cloud-storage

我正在尝试使用Google云端存储Java API将文件上传到Google云端存储,并在上传之前为该文件设置md5或crc32c校验和/哈希值。

我一直得到类似于下面显示的错误(对于md5和crc32c哈希)并且不知道我做错了什么:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "invalid",
    "message": "Provided CRC32C \"qtQiXA==\" doesn't match calculated CRC32C \"AAAAAA==\"."
   }
  ],
  "code": 400,
  "message": "Provided CRC32C \"qtQiXA==\" doesn't match calculated CRC32C \"AAAAAA==\"."
 }
}

如果在BlobInfo上没有设置md5或crc32c校验和值,则文件上载有效。在使用WriteChannel上传文件blob之前我想要实现的代码片段如下所示:

// Upload a blob to the identified bucket and use md5 or crc32c checksum 
BlobId blobId = BlobId.of(storageBucketName, sourceEvent.getFileName());
BlobInfo blobInfo = null;
Storage.BlobWriteOption blobWriteOption = null;

if(sourceEvent.getFileHash() != null && sourceEvent.getFileHashType() == FileIntegrityCheckType.CRC32C.getCheckType()) {
    blobInfo = BlobInfo.newBuilder(blobId).setStorageClass(
            GoogleCloudStorageClass.getStorageClass(storageClass)
    ).setCrc32c(sourceEvent.getFileHash()).build();
    blobWriteOption = Storage.BlobWriteOption.crc32cMatch();
} else if(sourceEvent.getFileHash() != null && sourceEvent.getFileHashType() == FileIntegrityCheckType.MD5.getCheckType()) {
    blobInfo = BlobInfo.newBuilder(blobId).setStorageClass(
            GoogleCloudStorageClass.getStorageClass(storageClass)
    ).setMd5(sourceEvent.getFileHash()).build();
    blobWriteOption = Storage.BlobWriteOption.md5Match();
} else {
    blobInfo = BlobInfo.newBuilder(blobId).setStorageClass(
            GoogleCloudStorageClass.getStorageClass(storageClass)).build();
}

我使用Google Guava Hashing API生成文件crc32c和md5哈希的方法如下所示:

    private byte[] generateCrc32CheckSum(Path file) {
        byte[] crc32CheckSum = new byte[0];

        if(file != null) {
            byte[] buffer = new byte[SysConstants.FILE_READ_BUFFER_SIZE];
            int limit = -1;
            HashFunction crc32cHashFunc = Hashing.crc32c();
            Hasher crc32cHasher = crc32cHashFunc.newHasher();

            try (FileInputStream fis = new FileInputStream(file.toFile())) {
                while ((limit = fis.read(buffer)) > 0) {
                    crc32cHasher.putBytes(buffer, 0, limit);
                }

//                    crc32CheckSum = crc32cHasher.hash().asBytes();
                crc32CheckSum = Ints.toByteArray(crc32cHasher.hash().asInt());

            } catch (IOException e) {
                e.printStackTrace(); 
            }
        }

        return crc32CheckSum;
    }

    private byte[] generateMd5Hash(Path file) {
        byte[] md5Hash = new byte[0];

        if(file != null) {
            byte[] buffer = new byte[SysConstants.FILE_READ_BUFFER_SIZE];
            int limit = -1;
            HashFunction md5HashFunc = Hashing.md5();
            Hasher md5Hasher = md5HashFunc.newHasher();

            try (FileInputStream fis = new FileInputStream(file.toFile())) {
                while ((limit = fis.read(buffer)) > 0) {
                    md5Hasher.putBytes(buffer, 0, limit);
                }

                md5Hash = md5Hasher.hash().asBytes();

            } catch (IOException e) {
                e.printStackTrace();            
            }
        }

        return md5Hash;
    }

然后,我使用以下方法执行Base64编码:

public void queueFileWithSizeAndIntegrityCheckToken(SourceEvent sourceEvent, FileTransferStatus queuedStatus) {
    if(isFileTransferReady(sourceEvent)) {
        String fileName = sourceEvent.getFileName();
        Path filePath = Paths.get(fileName);

        if(filePath != null) {
            long fileSize = filePath.toFile().length();

            if(fileSize > 0) {
                sourceEvent.setFileSize(fileSize);

                if (isIntegrityCheckEnabled) {
                    if (integrityCheckType.equalsIgnoreCase(FileIntegrityCheckType.CRC32C.getIntegrityCheckTokenType())) {
                        byte[] crc32CheckSum = generateCrc32CheckSum(filePath);

                        if(crc32CheckSum.length > 0) {
                            sourceEvent.setFileHash(BaseEncoding.base64().encode(crc32CheckSum));
                            sourceEvent.setFileHashType(FileIntegrityCheckType.CRC32C.getCheckType());
                        }
                    } else if (integrityCheckType.equalsIgnoreCase(FileIntegrityCheckType.MD5.getIntegrityCheckTokenType())) {
                        byte[] md5Token = generateMd5Hash(filePath);

                        if(md5Token.length > 0) {
                            sourceEvent.setFileHash(BaseEncoding.base64().encode(md5Token));
                            sourceEvent.setFileHashType(FileIntegrityCheckType.MD5.getCheckType());
                        }
                    }
                }

                fileTransferLogService.updateSourceEventStatus(sourceEvent,
                        queuedStatus);
            }
        }
    }
}

有人可以审核并让我知道我做错了什么吗?谢谢。

1 个答案:

答案 0 :(得分:0)

上述代码有效,Google云端存储服务或Google云端存储Java客户端库也没有问题。

问题已经解决,似乎是由Spring中的事务设置引起的,这显然影响了要上传的文件的正确处理以及生成所需的crc32c和md5哈希值。