2012-04-26 64 views
6

使用下面的德尔福XE2(更新4)代码:SignatureDoesNotMatch错误“文/ *”使用TAmazonStorageService.UploadObject

var 
    ConInfo: TAmazonConnectionInfo; 
    RespInfo: TCloudResponseInfo; 
    Service: TAmazonStorageService; 
    Content: TBytes; 
    Headers: TStringList; 
begin 
    ConInfo:=TAmazonConnectionInfo.Create(self); 
    ConInfo.AccountName:='YOUR ACCOUNT NAME'; 
    ConInfo.AccountKey:='YOUR ACCOUNT KEY'; 
    ConInfo.Protocol:='http'; 

    Service:=TAmazonStorageService.Create(ConInfo); 
    RespInfo:=TCloudResponseInfo.Create; 

    SetLength(Content, 128); 
    FillMemory(@Content[0], 128, Byte('x')); 

    Headers:=TStringList.Create; 
    Headers.Values['Content-type']:='text/plain'; 
    if not Service.UploadObject('YOUR BUCKET', 'test.txt', Content, TRUE, nil, Headers, amzbaPrivate, RespInfo) then 
    ShowMessage('Failed:' + RespInfo.StatusMessage); 

我总是在呼吁UploadObject得到一个错误:

失败:HTTP/1.1 403禁止 - 我们计算的请求签名 与您提供的签名不匹配。检查您的密钥并签署 方法。 (SignatureDoesNotMatch)

这仅当内容类型被设置为“文本/纯”,文本/ html“,或文本什么事情发生。使用完全相同的代码,如果您只是将内容类型更改为任何其他内容类型,例如'video/3gpp',那么它按预期工作,没有错误。被上传对象的实际内容是不相关的,并且与获取错误没有关系。

我已经追踪了Delphi中的Indy代码,但我很难理解为什么文本内容类型总是会出现这个错误。

任何想法?

回答

4

如果追加 “;字符集= ISO-8859-1” 的内容类型的字符串,然后它的工作原理:

Headers.Values['Content-type']:='text/plain; charset=ISO-8859-1'; 

通过代码步进我看到的Content-Type在TIdEntityHeaderInfo正在改变.SetHeaders(IdHTTPHeaderInfo.pas)从TIdHTTPProtocol.BuildAndSendRequest(IdHTTP.pas)中调用。

最终,它看起来像问题是TIdEntityHeaderInfo.SetContentType(IdHTTPHeaderInfo.pas)将字符集附加到内容类型,如果它是'文本'并且它还没有。它不应该在这些情况下更改内容类型,因为内容类型是要签名的字符串的一部分,所以在签名后更改它会使签名无效。

+0

很高兴您能够自己解决它。当尝试上传文本/ html时,这个问题完全相同。当时我使用的只是“html” - 但随后Internet Explorer在查看文件时遇到问题。感谢分享!!!!! – 2014-03-11 23:48:49

0

我有同样的问题。我还使用application/octet-stream作为内容类型,但仍有一些麻烦。之后,我发现存储桶名称必须小写(在美国标准区域中,亚马逊允许使用大写或混合大小写名称来定义存储区;但是,这些存储区不能通过HTTP API(包括TAmazonStorageService)访问。没有找到消息,我仍然有403错误(未经身份验证的用户)。 但是,我将名称更改为全部小写,它工作正常。 希望它有帮助

相关问题