我正在尝试使用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);
}
}
}
}
有人可以审核并让我知道我做错了什么吗?谢谢。
答案 0 :(得分:0)
上述代码有效,Google云端存储服务或Google云端存储Java客户端库也没有问题。
问题已经解决,似乎是由Spring中的事务设置引起的,这显然影响了要上传的文件的正确处理以及生成所需的crc32c和md5哈希值。