[英]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 中的部署方式未更新,因此我将按照我的建议放置部署步骤并验证它们是否有效:
激活 Cloud Shell 并运行:
从 github 克隆存储库: git clone https://github.com/RealKinetic/ftp-bucket.git
切换到目录: cd ftp-bucket
根据需要调整您的代码
创建一个 GCS 存储桶,如果您还没有,可以通过gsutil mb -p [PROJECT_ID] gs://[BUCKET_NAME]
创建一个
部署: gcloud functions deploy importFTP --stage-bucket [BUCKET_NAME] --trigger-http --runtime nodejs8
以我个人的经验,这比在两个功能中使用它更有效,除非您需要在同一云 function 中进行一些文件编辑
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.