2017-08-04 263 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

是的,我明白了。我修復了你的代碼,現在上傳的文件是正確的。檢查新的答案。 –