3

傳遞給我的Google雲端功能的event只能告訴我存儲桶和文件的名稱以及文件是否被刪除。是的,有更多的存在,但它似乎沒有那麼有用:如何從雲端函數中讀取類型爲.json的新雲存儲文件的內容?

{ timestamp: '2017-03-25T07:13:40.293Z', 
eventType: 'providers/cloud.storage/eventTypes/object.change', 
resource: 'projects/_/buckets/my-echo-bucket/objects/base.json#1490426020293545', 
data: { kind: 'storage#object', 
     resourceState: 'exists', 
     id: 'my-echo-bucket/base.json/1490426020293545', 
     selfLink: 'https://www.googleapis.com/storage/v1/b/my-echo-bucket/o/base.json', 
     name: 'base.json', 
     bucket: 'my-echo-bucket', 
     generation: '1490426020293545', 
     metageneration: '1', 
     contentType: 'application/json', 
     timeCreated: '2017-03-25T07:13:40.185Z', 
     updated: '2017-03-25T07:13:40.185Z', 
     storageClass: 'STANDARD', 
     size: '548', 
     md5Hash: 'YzE3ZjUyZjlkNDU5YWZiNDg2NWI0YTEyZWZhYzQyZjY=', 
     mediaLink: 'https://www.googleapis.com/storage/v1/b/my-echo-bucket/o/base.json?generation=1490426020293545&alt=media', contentLanguage: 'en', crc32c: 'BQDL9w==' } 
} 

如何得到內容和新的以.json文件的不僅僅是元數據上傳到GS鬥?

我試過event.data.selfLink,這是在存儲桶中的文件的URL使用npm:request(),並得到回一個授權錯誤:

"code": 401, "message": "Anonymous users does not have storage.objects.get access to object my-echo-bucket/base.json."

有關於閱讀的存儲桶上SO類似的問題,但可能在不同的平臺上。反正它是懸而未決

How do I read the contents of a file on Google Cloud Storage using javascript `

+1

注:這是一個[自我回答提問](http://stackoverflow.com/help/self-answer)。希望其他人認爲它很有用。如果你有更好/更清潔/更短的答案,我會考慮它。 – Paul

回答

5

你需要使用谷歌的存儲,而不是通過URL訪問客戶端庫。對URL使用request()只會在文件暴露給公衆訪問時才起作用。

將google雲存儲庫導入包含項目的npm託管目錄中。

npm i @google-cloud/storage -S 

npm page for google-cloud/storage有不俗的例子,但我不得不通過API讀一位看到一個簡單的方法來下載到內存中。

在Google Cloud Functions環境中,您不需要將任何api密鑰等作爲初始化提供給存儲。

const storage = require('@google-cloud/storage')(); 

通過關於文件的元數據可用於確定您是否真的需要該文件。

當您需要該文件時,您可以使用file.download函數下載該函數,該函數可以採用回調方式,也可以採用缺少回調的方式返回承諾。
但是,數據將作爲Buffer返回,因此您需要致電data.toString('utf-8')將其轉換爲utf-8編碼的字符串。

const storage = require('@google-cloud/storage')(); 

exports.logNewJSONFiles = function logNewJSONFiles(event){ 
    return new Promise(function(resolve, reject){ 
     const file = event.data; 
     if (!file){ 
      console.log("not a file event"); 
      return resolve(); 
     } 
     if (file.resourceState === 'not_exists'){ 
      console.log("file deletion event"); 
      return resolve(); 
     } 
     if (file.contentType !== 'application/json'){ 
      console.log("not a json file"); 
      return resolve(); 
     } 
     if (!file.bucket){ 
      console.log("bucket not provided"); 
      return resolve(); 
     } 
     if (!file.name){ 
      console.log("file name not provided"); 
      return resolve(); 
     } 
     (storage 
     .bucket(file.bucket) 
     .file(file.name) 
     .download() 
     .then(function(data){ 
      if (data) 
       return data.toString('utf-8'); 
     }) 
     .then(function(data){ 
      if (data) { 
       console.log("new file "+file.name); 
       console.log(data); 
       resolve(data); 
      } 
     }) 
     .catch(function(e){ reject(e); }) 
      ); 
    }); 
}; 

部署爲預期:

gcloud beta functions deploy logNewJSONFiles --stage-bucket gs://my-stage-bucket --trigger-bucket gs://my-echo-bucket 

記得在爲Stackdriver看:登錄頁面在谷歌雲平臺爲console.log條目。

更新:(2017年3月28日)。天真的代碼假設在第一次嘗試時傳輸完成OK。目前在嘗試使用谷歌雲端功能中的Google存儲時,會看到不少轉移ECONNRESET的轉移情況。希望這可以提高,但在此期間...使用npm:promise-retry有幫助,因爲通常在ECONNRESET之後的下一次嘗試中傳輸會通過OK。 promise-retry默認會嘗試10次。

以上代碼的最新promise-retry版本現在生存在npm:maybe-json。對於編寫我已經扔在一起npm:pipe-to-storage這將使用承諾重試如果一個字符串或函數返回一個新的可讀流被用作第一個參數。

+0

+1修復ECONNRESET錯誤。我必須強制我的cron函數每天重試幾次,以確保它能正確寫入所有文件。 –

1
npm install @google-cloud/storage --production 

的package.json:

{ 
    "main": "app.js", 
    "dependencies": { 
    "@google-cloud/storage": "^1.2.1" 
    } 
} 

你應該做到這一點npm ls顯示像npm ERR! missing:沒有錯誤。

app.js:

... 

    const storage = require("@google-cloud/storage")(); 
    storage. 
    bucket("mybucket"). 
    file("myfile.txt"). 
    download(function(err, contents) { 
     console.log(contents.toString()); 
    }); 
相關問題