node.js - 如何在 Google Cloud Function 的 /tmp 文件夹中下载文件,然后将其上传到 Google Cloud Storage
问题描述
所以我需要部署一个谷歌云功能,让我做两件事。
第一个是在 Cloud Function 的 /tmp 本地目录上下载 SFTP/FTP 服务器上的任何文件。然后,第二步是将这个文件上传到 Google Cloud Storage 的存储桶中。
实际上我知道如何上传,但我不知道如何将文件从 ftp 服务器下载到我的本地 /tmp 目录。
所以,实际上我已经编写了一个 GCF,它接收参数(在正文上)、允许我连接 FTP 服务器的配置(config)、文件名和路径。
对于我的测试,我使用了以下 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 以异步方式执行该块。一旦您的脚本完成了该操作,它就会立即继续执行脚本的其余部分。它不会等待“块”完成。因此,您的上传代码在下载完成之前运行。
你可以做两件事。第一个是将执行上传的所有代码移动到 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) {
....
}
}
推荐阅读
- macos - rsync --update 到 ext 磁盘复制未更改的文件
- javascript - fetch get 请求获取资源失败
- elasticsearch - 摄取处理器 foreach 或脚本以替换数组中的所有项目
- python - 从 pandas 列中提取 urls 信息
- python - 如何使用 pygame 在 Python 中保持 png 图像的透明度?
- java - 空指针异常密码程序
- python - Python Redis 每 2 分钟超时一次
- python - 如何更改我的 json 文件的某些值?
- javascript - VueJS将活动类附加到li标签而不是标签
- python - 如何将单列转换为正态或高斯分布。& 找到 95% 和 99% 的 CI