2017-08-04 211 views
0

使用我在其他主题中找到的代码。虽然accessKeyID和secretAccessKey验证正确,但我在验证时总会遇到签名不匹配。存储端点对于存储桶也是正确的。使用Delphi 10西雅图。 CloudComponents可能与该地区或(当地)时间有问题吗?用Delphi将文件上传到Amazon S3

Function Amazon_Upload (fileName, bucket, accessKeyID, secretAccessKey : String) : TCallResult; 
var 
    Service: TAmazonStorageService; 
    ConAmazon: TAmazonConnectionInfo; 
    info : TCloudResponseInfo; 
    upload_stream : TFileStream; 
    bytes : TBytes; 
begin 
    // create file 
    upload_stream := TFileStream.Create(fileName,fmOpenRead); 
    try 
    // filestream to tBytes 
    upload_stream.Position := 0; 
    SetLength(bytes, upload_stream.Size); 
    upload_stream.Write(bytes[0], upload_stream.Size); 
    ConAmazon := TAmazonConnectionInfo.Create(nil); 
    try 
     // amazon connection parameters 
     ConAmazon.AccountKey := secretAccessKey; 
     ConAmazon.AccountName := accessKeyID; 
     ConAmazon.QueueEndpoint := 'queue.amazonaws.com'; 
     ConAmazon.StorageEndpoint := 's3-eu-central-1.amazonaws.com'; 
     ConAmazon.TableEndpoint := 'sdb.amazonaws.com'; 
     ConAmazon.UseDefaultEndpoints := False; 
     // storage objects 
     info := TCloudResponseInfo.Create; 
     Service := TAmazonStorageService.Create(ConAmazon); 
     try 
     // upload document to storage 
     Service.UploadObject(Bucket, fileName, bytes, TRUE, nil, nil, amzbaPrivate, info); 
     // get results 
     Result.Callstatus := info.StatusCode; 
     Result.Success := info.StatusCode in [Ord(rrOK),ord(rrCreated),ord(rrNoContent)]; 
     Result.Response := TJSONObject.ParseJSONValue(info.StatusMessage); 
     If Assigned(OnLog) Then 
      FOnlog(info.StatusCode, ConAmazon.StorageEndpoint + #13#10 + bucket + #13#10 + accessKeyID + #13#10 + secretAccessKey, info.StatusMessage, ''); 
     finally 
     info.Free; 
     Service.Free; 
     end; 
    finally 
     ConAmazon.Free; 
    end; 
    finally 
    upload_stream.Free; 
    end; 
end; 
+0

我使用了一个非常类似的代码,我没有问题的地区。虽然当地时间需要明确界定。例如,在西班牙,我们处于+1时区时间,但加那利群岛处于0时区时间,几个电脑设置在西班牙语+1时区,并且手动将时钟更改为1小时以匹配当地小时。那些电脑无法连接到S3,它表示身份验证已过期。当这些PC被设置到正确的时区时,问题就消失了。 –

+0

这是基于您的代码马克:-)不能直接评论它,没有足够的repuation ..它不说过期,它表示签名不匹配,签名是基于secretaccesskey,时间戳和地区计算。 –

+0

很高兴看到它的帮助:-)。请检查您的时区是否设置正确。 –

回答

0

我已经稍微修改了您的代码,以使用TBytesStream而不是TFileStream来设置TBytes缓冲区上的文件内容。你必须阅读流,而不是写它。

现在它不会破坏它的内容。

Function Amazon_Upload (fileName, bucket, accessKeyID, secretAccessKey: String) : TCallResult; 
var 
    Service: TAmazonStorageService; 
    ConAmazon: TAmazonConnectionInfo; 
    info : TCloudResponseInfo; 
    upload_stream : TBytesStream; 
    bytes : TBytes; 
begin 
    // create file 
    upload_stream := TBytesStream.Create; 
    upload_stream.LoadFromFile(filename); 
    try 
    // filestream to tBytes 
    upload_stream.Position := 0; 
    SetLength(bytes, upload_stream.Size); 
    upload_stream.ReadBuffer(bytes, upload_stream.Size); 
    ConAmazon := TAmazonConnectionInfo.Create(nil); 
    try 
     // amazon connection parameters 
     ConAmazon.AccountKey := secretAccessKey; 
     ConAmazon.AccountName := accessKeyID; 
     ConAmazon.QueueEndpoint := 'queue.amazonaws.com'; 
     ConAmazon.StorageEndpoint := 's3-eu-central-1.amazonaws.com'; 
     ConAmazon.TableEndpoint := 'sdb.amazonaws.com'; 
     ConAmazon.UseDefaultEndpoints := False; 
     // storage objects 
     info := TCloudResponseInfo.Create; 
     Service := TAmazonStorageService.Create(ConAmazon); 
     try 
     // upload document to storage 
     Service.UploadObject(Bucket, ExtractFileName(fileName), bytes, TRUE, nil, nil, amzbaPrivate, info); 
     // get results 
     Result.Callstatus := info.StatusCode; 
     Result.Success := info.StatusCode in [Ord(rrOK),ord(rrCreated),ord(rrNoContent)]; 
     Result.Response := TJSONObject.ParseJSONValue(info.StatusMessage); 
     If Assigned(OnLog) Then 
      FOnlog(info.StatusCode, ConAmazon.StorageEndpoint + #13#10 + bucket + #13#10 + accessKeyID + #13#10 + secretAccessKey, info.StatusMessage, ''); 
     finally 
     info.Free; 
     Service.Free; 
     end; 
    finally 
     ConAmazon.Free; 
    end; 
    finally 
    upload_stream.Free; 
    end; 
end; 
+0

作品完美,谢谢! –

0

运行你的代码我发现了这个问题。只是改变这一行:

Service.UploadObject(Bucket, fileName, bytes, TRUE, nil, nil, amzbaPrivate, info); 

通过这条线:

Service.UploadObject(Bucket, ExtractFileName(fileName), bytes, TRUE, nil, nil, amzbaPrivate, info); 

文件的本地路径不能存在于远程调用(我猜它混淆了服务器,以为你正在尝试达到您没有权限的资源)。

+0

谢谢@Marc,我实际上在同一时间找到了这个。通过此代码,我可以立即上传PDF,但上传的文档已损坏。走近,但还没有:-) –

+0

是的,我明白了。我修复了你的代码,现在上传的文件是正确的。检查新的答案。 –

相关问题