用于文件上传的Firebase云功能 [英] Firebase cloud function for file upload

查看:151
本文介绍了用于文件上传的Firebase云功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个云功能,我写的上传文件到谷歌云存储:

I have this cloud function that I wrote to upload file to google cloud storage:

const gcs = require('@google-cloud/storage')({keyFilename:'2fe4e3d2bfdc.json'});

var filePath = file.path + "/" + file.name;

    return bucket.upload(filePath, {
        destination: file.name
    }).catch(reason => {
            console.error(reason);
    });

我用 formidable 来解析上传的文件我试着记录上传文件的属性,看起来很好;它上传到临时目录'/ tmp / upload_2866bbe4fdcc5beb30c06ae6c3f6b1aa / 但当我尝试将文件上传到gcs时出现此错误:

I used formidable to parse the uploaded file and I tried to log the properties of the uploaded file and it seems fine; it is uploaded to a temp dir '/tmp/upload_2866bbe4fdcc5beb30c06ae6c3f6b1aa/ but when I try to upload the file to the gcs am getting this error:

{ Error: EACCES: permission denied, stat '/tmp/upload_2866bbe4fdcc5beb30c06ae6c3f6b1aa/thumb_ttttttt.jpg'
    at Error (native)
  errno: -13,
  code: 'EACCES',
  syscall: 'stat',
  path: '/tmp/upload_2866bbe4fdcc5beb30c06ae6c3f6b1aa/thumb_ttttttt.jpg' }

我使用此html表单上传文件:

I am using this html form to upload the file:

<!DOCTYPE html>
<html>
<body>

<form action="https://us-central1-appname.cloudfunctions.net/uploadFile" method="post" enctype="multipart/form-data">
    Select image to upload:
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input type="submit" value="Upload Image" name="submit">
</form>

</body>
</html>


推荐答案

我从 Firebase支持团队

I got a solution from the Firebase Support Team

首先,代码包含对'强大'库的一个小误解。该行:

First, the code contains a small misunderstanding of the 'formidable' library. The line:

var filePath = file.path + "/" + file.name;

表示我们期望'formidable'以原始名称上传我们的文件,并将其存储在里面具有随机名称的临时目录。实际上,'强大'的作用是将文件上传到存储在'file.path'中的随机路径,而不再使用原始文件名。如果我们想要,我们可以通过阅读'file.name'来找出原始文件名是什么。

indicates that we're expecting that 'formidable' uploads our file with its original name, storing it inside a temporary directory with a random name. Actually, what 'formidable' does is upload the file to a random path stored in 'file.path', not using the original filename anymore at all. If we want we can find out what the original filename was by reading 'file.name'.

因此,代码的快速修补程序将更改:

The quick fix for the code is therefore to change:

var filePath = file.path + "/" + file.name;

只是:

var filePath = file.path;

其次,还有一个问题会导致代码出现问题:函数在异步工作完成之前终止在'form.parse(...)'完成。这意味着实际的文件上传可能会在函数已经完成时发生,因此它不再保留任何CPU或内存 - 上传速度会非常慢,甚至可能会失败。

Second, there's one more issue that can cause this code trouble: the function terminates before the asynchronous work done in 'form.parse(...)' is completed. That means the actual file upload will probably happen when the function has already said it's done, so it doesn't have any CPU or memory reserved anymore - the upload will go very slow, or maybe even fail.

对此的修复是在承诺中包装 form.parse(...)

The fix for that is to wrap the form.parse(...) in a promise:

exports.uploadFile = functions.https.onRequest((req, res) => {
   var form = new formidable.IncomingForm();
   return new Promise((resolve, reject) => {
     form.parse(req, function(err, fields, files) {
       var file = files.fileToUpload;
       if(!file){
         reject("no file to upload, please choose a file.");
         return;
       }
       console.info("about to upload file as a json: " + file.type);
       var filePath = file.path;
       console.log('File path: ' + filePath);

       var bucket = gcs.bucket('bucket-name');
       return bucket.upload(filePath, {
           destination: file.name
       }).then(() => {
         resolve();  // Whole thing completed successfully.
       }).catch((err) => {
         reject('Failed to upload: ' + JSON.stringify(err));
       });
     });
   }).then(() => {
     res.status(200).send('Yay!');
     return null
   }).catch(err => {
     console.error('Error while parsing form: ' + err);
     res.status(500).send('Error while parsing form: ' + err);
   });
 });

最后,您可能需要考虑使用Cloud Storage for Firebase上传文件而不是云功能。 Cloud Storage for Firebase允许您直接将文件上传到它,并且可以更好地工作:

它具有访问控制功能

它具有可恢复的上传/下载(非常适合连接不良)< br>
它可以接受任何大小的文件,没有超时问题

如果云函数应该运行以响应文件上传,你可以做更多的事情

Lastly, you may want to consider using the Cloud Storage for Firebase in uploading your file instead of Cloud functions. Cloud Storage for Firebase allows you to upload files directly to it, and would work much better:
It has access control
It has resumable uploads/downloads (great for poor connectivity)
It can accept files of any size without timeout-issues
If a Cloud Function should run in response to a file upload, you can do that and a lot more

这篇关于用于文件上传的Firebase云功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆