【问题标题】:AWS SDK iOS 2.0 S3 upload: add correct md5AWS SDK iOS 2.0 S3 上传:添加正确的 md5
【发布时间】:2014-10-15 14:46:44
【问题描述】:

我正在尝试使用适用于 iOS 2.0 的新 AWS 开发工具包将文件上传到 S3。 只要我不在请求中设置 contentMD5,上传就可以正常工作。

首先,我创建一个文件路径和一个 URL:

NSString *tempFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"s3tmp"];
NSURL *tempFileURL = [NSURL fileURLWithPath:tempFilePath];

接下来,我创建请求:

AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
uploadRequest.bucket = S3_BUCKETNAME;
uploadRequest.key = s3Key;
uploadRequest.body = tempFileURL;

然后我创建 md5。方便,这里有个github项目:https://github.com/JoeKun/FileMD5Hash 这是从文件创建md5。但是,我用 bashs md5 进行了交叉检查,它返回了相同的 md5 字符串。此外,如果我没有在请求中设置 contentMD5,则上传成功,并且在控制台中,相同的 md5 字符串显示为 eTag。所以我认为下一行计算的md5是正确的。

NSString *md5 = [FileHash md5HashOfFileAtPath:tempFilePath];

最后,我将 md5 添加到 uploadRequest 中:

uploadRequest.contentMD5 = md5;

并开始上传:

[[transferManager upload:uploadRequest] continueWithBlock:^id(BFTask *task) {
NSError *error = task.error;
if (error) {
NSDictionary *errorUserInfo = error.userInfo;
NSLog(@"Error %@: %@",[errorUserInfo objectForKey:@"Code"],[errorUserInfo objectForKey:@"Message"]);
dispatch_sync(dispatch_get_main_queue(), ^{
[weakSelf uploadFinishedUnsuccessful];
});
}
else {
NSLog(@"Upload success for file \n%@ to \n%@/%@",[tempFileURL absoluteString],S3_BUCKETNAME,s3Key);
dispatch_sync(dispatch_get_main_queue(), ^{
[weakSelf uploadFinishedSuccessful];
});
}
return nil;
}];

这总是返回一个错误: 错误 InvalidDigest:您指​​定的 Content-MD5 无效。

所以我尝试使用iOS的内置方法将md5包装成base64:

NSString *base64EncodedString = [[md5 dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];

我与另一个 base64 库交叉检查了这个。它返回相同的base64字符串,所以我认为base64字符串是正确的。我尝试将其设置为 contentMD5:

uploadRequest.contentMD5 = base64EncodedString;

我得到同样的错误: 错误 InvalidDigest:您指​​定的 Content-MD5 无效。

知道我做错了什么吗?

感谢您的回复!

【问题讨论】:

    标签: ios amazon-web-services amazon-s3


    【解决方案1】:

    您需要对 MD5 哈希的 binary 表示进行 base64 编码...而不是 hex 表示,这听起来像是您可能正在做的。

    如果编码正确,结果值将是大约 24 个字符的长度……如果编码不正确,则长度会增加一倍。

    【讨论】:

    • 非常感谢您的帮助,迈克尔!我像这样创建一个 NSData 对象: [md5 dataUsingEncoding:NSUTF8StringEncoding] ——这不是 md5 的二进制表示吗?然后我将该 NSData 对象编码为 base64。有错吗?
    • Objective C 不是我的专业领域。 S3 是,并且在此之前我已经实现了正确计算 S3 期望的 Content-MD5 的代码。您对 md5 与 etag 相同的描述使我怀疑您从正确的值开始,因此最可能的问题是您从错误的起点编码为 base64。由您的代码计算的一个 md5 总和和相应的 b64 等效项的示例是什么?我会看看我想出什么价值。
    • md5 为:“28e01cf6608332ae51d63af3364d77f2”(本地和 S3 上的 eTag)。结果 base64 是 "MjhlMDFjZjY2MDgzMzJhZTUxZDYzYWYzMzY0ZDc3ZjI=" - 48 个字符,你是对的!!那么“正确”和“错误”有什么区别呢?
    【解决方案2】:

    好的,Michaels cmets 让我找到了正确的方向。经过反复阅读,我终于明白了他试图告诉我的内容。对于其他难以掌握这个概念的人,我尝试解释一下: 像“28e01cf6608332ae51d63af3364d77f2”这样的 md5 字符串是 16 字节摘要的十六进制表示。这意味着,这 32 个字符中的每 2 个字符代表 1 个字节。

    28 = 第一个字节,e0 = 第二个字节,1c = 第三个字节,依此类推,直到有 16 个字节。

    content-md5 标头需要 base64 编码的 16 字节不是十六进制表示。 其他很方便的方法

    [FileHash md5HashOfFileAtPath:tempFilePath]
    

    仅将此十六进制表示形式返回为 NSString。因此,我可以在字符串转换完成之前深入提取字节,或者将字符串重新转换为 NSData。 我选择了后者,代码 sn-p 我找到了here

    //convert the md5 hexadecimal string representation BACK to the NSData byte representation
        NSMutableData *md5Data= [[NSMutableData alloc] init];
        unsigned char whole_byte;
        char byte_chars[3] = {'\0','\0','\0'};
        int i;
        for (i=0; i < [md5 length]/2; i++) {
            byte_chars[0] = [md5 characterAtIndex:i*2];
            byte_chars[1] = [md5 characterAtIndex:i*2+1];
            whole_byte = strtol(byte_chars, NULL, 16);
            [md5Data appendBytes:&whole_byte length:1];
        }
    
        //base64-encode the NSData byte representation
        NSString *base64EncodedString = [md5Data base64EncodedStringWithOptions:0];
    
        uploadRequest.contentMD5 = base64EncodedString;
    

    这个 base64encodedString 终于返回了成功响应!谢谢迈克尔!

    【讨论】:

    • 我已将 md5 字符串添加到 S3PutObjectRequest 作为 s3PutObjectRequest.contentMD5 = base64EncodedString; s3PutObjectRequest.httpMethod = @"PUT";但是当我尝试从 S3PutObjectResponse 中检索 eTag 时,我得到 ErrorCode:BadDigest, Message:The Content-MD5 you specified does not match what we received。任何原因 ??我已经把我的问题放在这里请添加评论我对这个原因有任何想法stackoverflow.com/questions/29847564/…
    猜你喜欢
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 2022-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多