Node.js 在Google云函数中从电子邮件上载和解压.zip文件完成后删除.zip节点JS
我收到一封包含一个.zip文件的电子邮件。现在我正试图上传到地面军事系统,并处理(大容量解压缩)到自己的文件夹文件。对我来说,为这样一个小动作运行大容量数据流似乎有些过头了 我曾考虑使用“解压流”包,但直到现在,我还没有想出一个有效的解决方案来解决我的问题 甚至可以在云函数中处理这样的文件吗?或者,如果没有一个专门的服务器来处理解压缩,然后将内容上传到GCS,那就没有办法了 这是我的密码:Node.js 在Google云函数中从电子邮件上载和解压.zip文件完成后删除.zip节点JS,node.js,google-cloud-platform,google-cloud-functions,google-cloud-storage,node-modules,Node.js,Google Cloud Platform,Google Cloud Functions,Google Cloud Storage,Node Modules,我收到一封包含一个.zip文件的电子邮件。现在我正试图上传到地面军事系统,并处理(大容量解压缩)到自己的文件夹文件。对我来说,为这样一个小动作运行大容量数据流似乎有些过头了 我曾考虑使用“解压流”包,但直到现在,我还没有想出一个有效的解决方案来解决我的问题 甚至可以在云函数中处理这样的文件吗?或者,如果没有一个专门的服务器来处理解压缩,然后将内容上传到GCS,那就没有办法了 这是我的密码: const os = require('os'); const fs = require('fs'); c
const os = require('os');
const fs = require('fs');
const { Storage } = require('@google-cloud/storage');
const storage = new Storage();
// Node.js doesn't have a built-in multipart/form-data parsing library.
// Instead, we can use the 'busboy' library from NPM to parse these requests.
const Busboy = require('busboy');
exports.uploadZIPFile = (req, res) => {
if (req.method !== 'POST') {
// Return a "method not allowed" error
return res.status(405).end();
}
const busboy = new Busboy({ headers: req.headers });
const tmpdir = os.tmpdir();
for (a in req.headers) {
console.log(`Header: ${a}`);
}
// This object will accumulate all the fields, keyed by their name
const fields = {};
// This code will process each non-file field in the form.
busboy.on('field', (fieldname, val) => {
// TODO(developer): Process submitted field values here
console.log(`Processed field ${fieldname}: ${val}.`);
fields[fieldname] = val;
});
// This object will accumulate all the uploaded files, keyed by their name.
const uploads = {};
const fileWrites = [];
// This code will process each file uploaded.
busboy.on('file', (fieldname, file, filename) => {
// Note: os.tmpdir() points to an in-memory file system on GCF
// Thus, any files in it must fit in the instance's memory.
console.log(`Processed file ${filename} - ${fieldname} - ${file}`);
const filepath = path.join(tmpdir, filename);
uploads[fieldname] = filepath;
const writeStream = fs.createWriteStream(filepath);
file.pipe(writeStream);
// File was processed by Busboy; wait for it to be written to disk.
const promise = new Promise((resolve, reject) => {
file.on('end', () => {
writeStream.end();
});
writeStream.on('finish', resolve);
writeStream.on('error', reject);
});
fileWrites.push(promise);
});
// Triggered once all uploaded files are processed by Busboy.
// We still need to wait for the disk writes (saves) to complete.
busboy.on('finish', async () => {
await Promise.all(fileWrites);
// TODO(developer): Process saved files here
for (const file in uploads) {
async function upload2bucket() {
// Uploads a local file to the bucket
const bucketName = 'myBucket';
const todayDate = new Date().toISOString().slice(0, 10);
await storage.bucket(bucketName).upload(uploads[file], {
// Support for HTTP requests made with `Accept-Encoding: gzip`
gzip: true,
// By setting the option `destination`, you can change the name of the
// object you are uploading to a bucket.
destination:
'zip-inbox/' + todayDate + '_' + uploads[file].substring(5),
metadata: {
// Enable long-lived HTTP caching headers
// Use only if the contents of the file will never change
// (If the contents will change, use cacheControl: 'no-cache')
cacheControl: 'no-cache',
},
});
console.log(`${filename} uploaded to ${bucketName}.`);
}
if (uploads[file].endsWith('.zip')) {
await upload2bucket();
}
console.log(`${file}: ${uploads[file]}`);
//fs.unlinkSync(file);
}
res.status(200).send('Success');
});
busboy.end(req.rawBody);
};
云功能非常适用于小任务,这些小任务花费的时间很少。如果您有类似的需求—您只想在需要时为工作单元旋转一个实例,但无法预测执行它的时间,我建议使用Cloud Run,看看这个云函数对于花费时间很短的小任务非常有用。如果您有类似的需求-您只想在需要时为一个工作单元旋转一个实例,但无法预测执行它的时间,我建议使用Cloud Run,看看这个您可以用几个函数替换您的“无所不能”云函数,并用消息或(2021年1月发布)创建一个管道 我还建议使用包来简化云函数定义 管道可以是这样的:
import*作为“firebase函数”中的函数;
从'@googlecloud/PubSub'导入{PubSub};
const REGION='您的谷歌云区域';//e、 g.欧洲-西方1
const PUBSUB_TOPIC_UNPACK_ZIP='your-TOPIC-name-for-step-2';
/**
*第一步。
*/
exports.getFromEmailAndUploadToStorage=函数
.地区(地区)
.朗威({
内存:“256MB”,
timeoutSeconds:540,//最大执行持续时间为9分钟
最大实例:1
})
pubsub.先生
.时间表(每15分钟一次)
.时区(“亚洲/海参崴”)
.onRun(异步){
const filepath=等待您的逻辑发送电子邮件并上载到存储();
if(文件路径){
const messagePayload={filepath};
log('将消息发布到主题:',PUBSUB_topic_UNPACK_ZIP);
log('Payload:',JSON.stringify(messagePayload));
等待新的PubSub().topic(PubSub_topic_UNPACK_ZIP)。publishMessage({
json:messagePayload
});
}
});
/**
*第二步。
*/
exports.unzipFilesInStorage=函数
.地区(地区)
.朗威({
内存:“256MB”,
timeoutSeconds:540,//最大执行持续时间为9分钟
最大实例:1
})
pubsub.先生
.topic(PUBSUB\u topic\u UNPACK\u ZIP)
.onPublish(异步(消息、上下文)=>{
const{filepath}=message?.json;
如果(!filepath){
抛出新错误('未设置文件路径');
}
//你的解压逻辑在这里。
//解压后,您可以通过PubSub消息进一步传递结果。
});
您可以使用多个函数替换“无所不能”云函数,并使用消息或(2021年1月发布)创建管道
我还建议使用包来简化云函数定义
管道可以是这样的:
import*作为“firebase函数”中的函数;
从'@googlecloud/PubSub'导入{PubSub};
const REGION='您的谷歌云区域';//e、 g.欧洲-西方1
const PUBSUB_TOPIC_UNPACK_ZIP='your-TOPIC-name-for-step-2';
/**
*第一步。
*/
exports.getFromEmailAndUploadToStorage=函数
.地区(地区)
.朗威({
内存:“256MB”,
timeoutSeconds:540,//最大执行持续时间为9分钟
最大实例:1
})
pubsub.先生
.时间表(每15分钟一次)
.时区(“亚洲/海参崴”)
.onRun(异步){
const filepath=等待您的逻辑发送电子邮件并上载到存储();
if(文件路径){
const messagePayload={filepath};
log('将消息发布到主题:',PUBSUB_topic_UNPACK_ZIP);
log('Payload:',JSON.stringify(messagePayload));
等待新的PubSub().topic(PubSub_topic_UNPACK_ZIP)。publishMessage({
json:messagePayload
});
}
});
/**
*第二步。
*/
exports.unzipFilesInStorage=函数
.地区(地区)
.朗威({
内存:“256MB”,
timeoutSeconds:540,//最大执行持续时间为9分钟
最大实例:1
})
pubsub.先生
.topic(PUBSUB\u topic\u UNPACK\u ZIP)
.onPublish(异步(消息、上下文)=>{
const{filepath}=message?.json;
如果(!filepath){
抛出新错误('未设置文件路径');
}
//你的解压逻辑在这里。
//解压后,您可以通过PubSub消息进一步传递结果。
});
此过程完全可以预测。看见9分钟是一个非常消耗的时间。电子邮件服务器对附件有严格的限制,邮件大小约为10-20-30兆。每个电子邮件附件下载并上传到谷歌存储不能/不应该超过9分钟。每一个这样大小的拉链也不能/sho