【发布时间】:2018-06-07 16:17:09
【问题描述】:
我正在尝试使用 Google Cloud Storage Java API 将文件上传到 Google Cloud Storage,并在上传前为文件设置 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 之前尝试实现的代码 sn-p 如下所示:
// 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);
}
}
}
}
有人可以检查并告诉我我做错了什么吗?谢谢。
【问题讨论】:
-
不是答案,但
AAAAAA==是空文件的CRC32C。这有帮助吗?我的意思是,还有什么会导致您上传空文件吗? -
我怀疑我上传的是一个空文件。如果我没有在 BlobInfo 对象上设置 crc32c 或 md5 哈希,则文件会正常上传。我只有在设置这些哈希类型和值时才会遇到问题。