使用以下Delphi XE2(更新4)代码:
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 Forbidden - 我们计算的请求签名 与您提供的签名不符。检查您的密钥并签名 方法。 (SignatureDoesNotMatch)
仅当Content-type设置为'text / plain','text / html'或文本内容时才会发生这种情况。使用完全相同的代码,如果您只是将内容类型更改为任何其他内容类型,例如'video / 3gpp',然后按预期工作,没有错误。上传的对象的实际内容不相关,与获取错误无关。
我已经通过Delphi中的Indy代码进行了跟踪,但我很难理解为什么文本内容类型总是会出现此错误。
有什么想法吗?
答案 0 :(得分:4)
如果您将“; charset = ISO-8859-1”附加到Content-Type字符串,那么它可以工作:
Headers.Values['Content-type']:='text/plain; charset=ISO-8859-1';
单步执行代码我看到TIdEntityHeaderInfo.SetHeaders(IdHTTPHeaderInfo.pas)中的Content-Type正在更改,该内容从TIdHTTPProtocol.BuildAndSendRequest(IdHTTP.pas)调用。
最终,看起来问题是TIdEntityHeaderInfo.SetContentType(IdHTTPHeaderInfo.pas)将字符集附加到内容类型(如果它是'text'且它还没有)。它不应该在这些情况下更改内容类型,因为内容类型是要签名的字符串的一部分,因此在签名后更改它会使签名无效。
答案 1 :(得分:0)
我遇到了同样的问题。我还使用application / octet-stream作为内容类型,但仍然遇到了一些麻烦。后来,我发现存储桶名称必须是小写的(在美国标准区域,亚马逊允许使用大写或混合大小写名称定义存储桶;但是,这些存储桶不能通过HTTP API(包括TAmazonStorageService)访问。找不到消息,我仍然收到403错误(未经身份验证的用户)。 但是,我将名称改为全部小写,它运行正常。 希望它有所帮助