2017-06-22 88 views
3

我試圖從谷歌雲存儲(谷歌播放發佈的應用程序的日誌文件)下載一些文件。從谷歌雲存儲下載總是不正確的哈希

我的代碼看起來像這樣

Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "my-service-account-credential.json", EnvironmentVariableTarget.Process); 
StorageClient storageClient = StorageClient.Create(); 

var bucketName = "mybucketname"; 
var buckets = storageClient.GetBucket(bucketName); 
var objects = storageClient.ListObjects(bucketName).ToList(); 
foreach (var o in objects) 
{ 
    try 
    { 
     Directory.CreateDirectory(Path.GetDirectoryName(o.Name)); 
     using (var fs = File.Open(o.Name, FileMode.OpenOrCreate)) 
     { 
      await storageClient.DownloadObjectAsync(bucketName, o.Name, fs);            
     } 
    } 
    catch (Exception e) 
    { 
     if (e.Message.StartsWith("Incorrect hash")) 
     { 
      continue; 
     } 
     throw; 
    } 
} 

的代碼實際上似乎很好地工作(通過查看實際下載的文件的內容來看,它是CSV文件)。但正如你所看到的,我已經實現了一個令人討厭的嘗試catch/hack,因爲我下載的每個文件都會拋出一個異常,指出hash不正確。我假設客戶端庫將下載內容的散列值與存儲區的散列值進行比較,並且這些散列值並不相同,導致它是一個例外。

唯一的例外是:

System.IO.IOException: Incorrect hash: expected 'DXpVGw==' (base64), was '2RMrcw==' (base64) 
    at Google.Cloud.Storage.V1.StorageClientImpl.<DownloadObjectAsyncImpl>d__48.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
    at MyClass.GoogleBucket.Functions.<DownloadGoogleBucketLogs>d__1.MoveNext() in mycode.cs:line 51 

所以我的問題是你如何下載對象,沒有得到這個例外,顯然一個是不應該做的我做了什麼。

+0

您能否包含完整的例外詳情? – mjwills

+0

我添加了異常詳細信息,如果有幫助的話。請注意,我嘗試了不同的時間,許多文件始終發生異常。 – sjkp

+0

我不知道這是否與客戶端庫有關。您能否根據他們的GCS元數據告訴我對象的內容類型和內容編碼? –

回答

6

TL; DR:更新到2.1.0。 (或者,如果你絕望,那麼在此之前取回並建立源代碼。)

這是一個棘手的問題。

問題是HttpClient在運行中自動解壓縮數據,但服務器提供的散列是用於壓縮內容的。

我們現在對REST API支持庫和Google.Cloud.Storage.V1庫進行了更改,以便在解壓縮之前攔截並散列下載的數據。這些變化在Github中合併,並將在2.1.0版本發佈,我預計將在1月初發布。

請注意,這不會修復客戶端解壓縮被禁用的單獨邊角情況,導致服務器端解壓縮,但仍然使用壓縮內容的散列。我們是tracking that separately,但它不會影響這裏的示例代碼,因爲如果您在初始化程序中創建了StorageService明確禁用的gzip支持,然後創建了StorageClient以包裝該服務,您只能看到它。