如何通过HTTP Google Cloud Function上传图像文件? [英] How to upload image file via HTTP Google Cloud Function?

查看:95
本文介绍了如何通过HTTP Google Cloud Function上传图像文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读有关如何将图像上传到存储桶以及如何通过后台功能进行后期处理的教程.但是我的要求是上传图像,进行后处理并立即通过HTTP函数返回结果.请告诉我这是否是正确的方法,因为我对此没有多少在线资料.这是我的处理方法:

I have read tutorials on how to upload the image to a bucket and do post processing via background function. But my requirement is to upload the image, do post processing and return the result immediately via HTTP function. Please let me know if this is the correct way to do or not as I didn't get much material online on this. Here is how I went about it:

HTTP Cloud功能:

HTTP Cloud function:

exports.uploadImage = function (req, res){
 var file = req.body.file;
 uploadSomewhere(file)(); < post-processing code which is working fine >

UI形式:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script> 
<script src="http://malsup.github.com/jquery.form.js"></script>
<form id="myForm" action="<cloud_function_url>/uploadImage" method="post"> 
  <label for="file">Choose file to upload</label>
  <input type="file" id="file" name="file" multiple>
  <input type="submit" value="Submit" /> 
</form>

<script> 
 $(document).ready(function() { 
  $('#myForm').ajaxForm(function() { 
 }); 
}); 
</script>

问题是,在部署功能之后,当我从存在功能的文件夹中上传图像时,图像就被上传了.但是,如果我从其他任何位置上传图像,则会返回错误消息:

The problem is, after I deployed the function, when I upload the image from the folder where function is present, image gets uploaded. But if I upload the image from any other location, it returns me error:

错误:上传图片文件时出现错误....-错误:ENOENT:没有此类文件或目录,请打开"...".

Error: Error in uploading image file .... - Error: ENOENT: no such file or directory, open '....'

请让我知道我在做什么错或者您需要更多信息.

Please let me know what am I doing wrong or if you need more information.

推荐答案

此处提供了用于将文件直接上传到Cloud Functions的示例代码: Firebase Realtime数据库来管理客户端上的状态.

There is sample code for uploading files directly to Cloud Functions here: https://cloud.google.com/functions/docs/writing/http#multipart_data_and_file_uploads, but be aware there is a file size limit when using this approach (10MB). If you have files larger than that, I recommend you use the Cloud Storage approach and use something like the Firebase Realtime Database to manage the state on the client.

因此,您可以使用Cloud Function生成签名的上传URL,然后使用RTDB跟踪客户端的进度.返回URL 对要跟踪进度的数据库位置的引用.客户端将在此位置查看更新.然后,客户端将文件上传到Cloud Storage,并触发第二个功能.在后处理之后,它会更新RTDB,这会将更新下推到客户端.从客户端的角度来看,这都是 synchronous ,但实际上是一系列异步操作,在数据库中具有状态合并.

So, you generate the signed upload URL using a Cloud Function, then use the RTDB to track progress for the client. Return the URL and a reference to the location in the DB where you're going to track progress. The client would watch this location for updates. The client then uploads the file to Cloud Storage and the second function is triggered. After post processing it updates the RTDB which pushes the update down to the client. From the client's perspective this is all synchronous, but it's actually a series of async operations with state coalescing in the database.

如果您对文件大小<没问题,请参见以下文档中的内联更新示例代码. 10MB:

Here's the sample code for inline updates taken from the docs if you're OK with file sizes < 10MB:

/**
 * Parses a 'multipart/form-data' upload request
 *
 * @param {Object} req Cloud Function request context.
 * @param {Object} res Cloud Function response context.
 */
const path = require('path');
const os = require('os');
const fs = require('fs');

// 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.uploadFile = (req, res) => {
  if (req.method === 'POST') {
    const busboy = new Busboy({ headers: req.headers });
    const tmpdir = os.tmpdir();

    // This object will accumulate all the fields, keyed by their name
    const fields = {};

    // This object will accumulate all the uploaded files, keyed by their name.
    const uploads = {};

    // 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;
    });

    let 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}`);
      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', () => {
      Promise.all(fileWrites)
        .then(() => {
          // TODO(developer): Process saved files here
          for (const name in uploads) {
            const file = uploads[name];
            fs.unlinkSync(file);
          }
          res.send();
        });
    });

    busboy.end(req.rawBody);
  } else {
    // Return a "method not allowed" error
    res.status(405).end();
  }
};

这篇关于如何通过HTTP Google Cloud Function上传图像文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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