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

查看:17
本文介绍了文件上传的 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 支持团队获得了解决方案

所以第一件事:

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

我们不需要 file.name,因为 file.path 是文件的完整路径(包括文件名).

we dont need the file.name since the file.path is full path of the file (including the file name).

所以改为这样:

var filePath = file.path;

其次,函数在 'form.parse(...)' 中的异步工作完成之前终止.这意味着在函数执行结束时,实际的文件上传可能仍在进行中.

Second, the function terminates before the asynchronous work in 'form.parse(...)' is completed. That means the actual file upload might still be in progress while the function execution has ended.

解决方法是将 form.parse(...) 包装在一个 Promise 中:

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 函数.Cloud Storage for Firebase 允许您将文件直接上传到它,而且效果会更好:

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:

  1. 它有访问控制
  2. 它具有可恢复的上传/下载(非常适合连接不良)
  3. 它可以接受任何大小的文件而不会出现超时问题
  4. 如果你想在文件上传时触发云函数,你可以做到这一点,还有更多

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

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