簡體   English   中英

如何在 Google Cloud Function 的 /tmp 文件夾中下載文件,然后將其上傳到 Google Cloud Storage

[英]How to download files in /tmp folder of Google Cloud Function and then upload it in Google Cloud Storage

所以我需要部署一個谷歌雲 Function 允許我做兩件事。

第一個是在雲 Function 的 /tmp 本地目錄上的 SFTP/FTP 服務器上下載任何文件。 然后,第二步是將這個文件上傳到 Google Cloud Storage 的存儲桶中。

實際上我知道如何上傳,但我不知道如何從 ftp 服務器下載文件到我的本地 /tmp 目錄。

所以,實際上我已經編寫了一個 GCF,它接收參數(在主體上)、配置(config)以允許我在 FTP 服務器上連接、文件名和路徑。

對於我的測試,我使用了以下 ftp 服務器測試: https://www.sftp.net/public-online-sftp-servers與此配置。

{
    config:
    {
        hostname: 'test.rebex.net',
        username: 'demo',
        port: 22,
        password: 'password'
    },
    filename: 'FtpDownloader.png',
    path: '/pub/example'
}

下載后,我開始上傳。 為此,我檢查是否在 UPLOAD 之前在 '/tmp/filename' 中找到了 DOWNLOAD 文件,但這里的文件比較緊張。

請參閱以下代碼:

exports.transferSFTP = (req, res) =>
{
    let body = req.body;
    if(body.config)
    {
        if(body.filename)
        {
            //DOWNLOAD
            const Client = require('ssh2-sftp-client');
            const fs = require('fs');

            const client = new Client();

            let remotePath
            if(body.path)
                remotePath = body.path + "/" + body.filename;
            else
                remotePath = "/" + body.filename;

            let dst = fs.createWriteStream('/tmp/' + body.filename);

            client.connect(body.config)
            .then(() => {
                console.log("Client is connected !");
                return client.get(remotePath, dst);
            })
            .catch(err => 
                {
                    res.status(500);
                    res.send(err.message);   
                })
           .finally(() => client.end());


           //UPLOAD
            const {Storage} = require('@google-cloud/storage');

            const storage = new Storage({projectId: 'my-project-id'});

            const bucket = storage.bucket('my-bucket-name');

            const file = bucket.file(body.filename);

            fs.stat('/tmp/' + body.filename,(err, stats) =>
            {
                if(stats.isDirectory())
                {
                    fs.createReadStream('/tmp/' + body.filename)
                        .pipe(file.createWriteStream())
                        .on('error', (err) => console.error(err))
                        .on('finish', () => console.log('The file upload is completed !!!'));

                    console.log("File exist in tmp directory");
                    res.status(200).send('Successfully executed !!!')
                }
                else
                {
                    console.log("File is not on the tmp Google directory");
                    res.status(500).send('File is not loaded in tmp Google directory')
                }
            });
        }
        else res.status(500).send('Error: no filename on the body (filename)');
    }
    else res.status(500).send('Error: no configuration elements on the body (config)');
}

因此,我收到以下消息:“文件未加載到 tmp Google 目錄中”,因為在 fs.stat() 方法之后,stats.isDirectory() 為 false。 在我使用 fs.stats() 方法檢查文件是否在這里之前,我剛剛編寫了具有相同文件名但沒有內容的文件。 因此,我得出的結論是,我的上傳工作,但沒有 DONWLOAD 文件,很難將其復制到 Google 雲存儲中。

感謝您的時間,我希望我能找到解決方案。

問題是在執行上傳的代碼開始運行之前,您沒有等待下載完成。 雖然您確實有一個 catch() 語句,但這還不夠。

將第一部分(下載)視為單獨的代碼塊。 您已經告訴 Javascript 到 go 異步執行該塊。 一旦您的腳本完成此操作,它就會立即繼續執行您的腳本的 rest。 它不會等待“塊”完成。 因此,您的上傳代碼在下載完成之前運行。

你可以做兩件事。 第一個是將執行上傳的所有代碼移動到 get() 調用之后的“then”塊中(順便說一句,您可以使用 fastGet() 來簡化事情)。 例如

client.connect(body.config)
 .then(() => {
   console.log("Client is connected !");
   return client.fastGet(remotePath, localPath);
 })
 .then(() => {
    // do the upload
  }) 
  .catch(err => {
     res.status(500);
     res.send(err.message);   
  })
 .finally(() => client.end());

另一種選擇是使用 async/await,這將使您的代碼看起來更“同步”。 類似於(未經測試)的東西

async function doTransfer(remotePath, localPath) {
  try {
    let client - new Client();
    await client.connect(config);
    await client.fastGet(remotePath, localPath);
    await client.end();
    uploadFile(localPath);
  } catch(err) {
    ....
   }
}

是一個 github 項目,它回答了與您類似的問題。

在這里,他們部署了一個 Cloud Function 從 FTP 下載文件並將它們直接上傳到存儲桶,跳過了獲取臨時文件的步驟。

該代碼有效,此 github 中的部署方式未更新,因此我將按照我的建議放置部署步驟並驗證它們是否有效:

  1. 激活 Cloud Shell 並運行:

  2. 從 github 克隆存儲庫: git clone https://github.com/RealKinetic/ftp-bucket.git

  3. 切換到目錄: cd ftp-bucket

  4. 根據需要調整您的代碼

  5. 創建一個 GCS 存儲桶,如果您還沒有,可以通過gsutil mb -p [PROJECT_ID] gs://[BUCKET_NAME]創建一個

  6. 部署: gcloud functions deploy importFTP --stage-bucket [BUCKET_NAME] --trigger-http --runtime nodejs8

以我個人的經驗,這比在兩個功能中使用它更有效,除非您需要在同一雲 function 中進行一些文件編輯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM