Как загрузить файлы в папку / tmp функции Google Cloud и затем загрузить ее в Google Cloud Storage - PullRequest
0 голосов
/ 19 сентября 2019

Поэтому мне нужно развернуть облачную функцию Google, которая позволит мне сделать 2 вещи.

Первая - это ЗАГРУЗИТЬ любые файлы на SFTP / FTP-сервере в локальный каталог / tmp облачной функции.Затем, второй шаг, это ЗАГРУЗИТЬ этот файл в корзину в облачном хранилище Google.

На самом деле я знаю, как загрузить, но я не понимаю, как ЗАГРУЗИТЬ файлы с сервера ftp на мой локальный / tmpdirectory.

Итак, на самом деле я написал 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'
}

После моей ЗАГРУЗКИ я запускаю свою ЗАГРУЗКУ.Для этого я проверяю, нашел ли я файл ЗАГРУЗИТЬ в «/ tmp / filename», прежде чем ЗАГРУЗИТЬ, но файл здесь ненадежный.

См. Следующий код:

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.

Спасибо за ваше время и надеюсь, что найду решение.

Ответы [ 2 ]

1 голос
/ 25 сентября 2019

Проблема в том, что вы не дожидаетесь завершения загрузки, прежде чем начнется запуск кода, который выполняет загрузку.Хотя у вас есть оператор catch (), этого недостаточно.

Думайте о первой части (загрузке) как об отдельном блоке кода.Вы сказали Javascript асинхронно отключать блок do do.Как только ваш сценарий сделает это, он сразу же приступит к выполнению остальной части вашего сценария.Он не ждет завершения блока.В результате ваш код для загрузки будет запущен до завершения загрузки.

Есть две вещи, которые вы можете сделать.Первым было бы переместить весь код, выполняющий загрузку, в блок «then» после вызова get () (кстати, вы могли бы упростить задачу с помощью 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) {
    ....
   }
}
0 голосов
/ 20 сентября 2019

здесь - это проект github, который решает ту же проблему, что и вы.

здесь они развертывают облачную функцию для загрузки файла с 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

По моему личному опыту это более эффективно, чем иметь его в двух функциях, если вам не нужно выполнять некоторыередактирование файлов в рамках одной и той же облачной функции

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...