Processing Multi-File Uploads with Serverless

Last updated: 2021-03-03 10:38:50

    Overview

    To use Tencent Cloud Serverless to process HTTP requests that upload multiple files with multipart/form-data, the Base64 Encoding feature of API Gateway is needed to encode the multipart byte stream in the HTTP source request into a string. In this way, the HTTP Event can be serialized before it is passed to SCF for processing.

    SCF obtains and decodes the Base64-encoded body of the event passed by API Gateway. The generated byte stream is the same as that of a normal HTTP request, which can be processed normally. In Node.JS, we can use libraries such as busboy to process it.

    Directions

    Step 1. Create a cloud function

    1. Log in to the SCF console.
    2. On the Function Service page, click Create to create a Node.js cloud function.
      Parameters involved in the creation process are as follows:
    3. Click Complete.

    Step 2. Write and deploy the code

    1. After you created the cloud function, write the code that processes multipart/form-data by referring to the following code:

      // handler.js
      "use strict";
      const stream = require("stream");
      const Busboy = require("busboy");
      
      /** Process user upload (POST) */
      const handlePost = (event) => {
      return new Promise((resolve, reject) => {
       const busboy = new Busboy({ headers: event.headers });
       let html = "";
       /** Receive the file */
       busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
         let buf = Buffer.alloc(0);
         console.log({ fieldname });
         /** Receive the data blocks of the file and concatenate the buffer */
         file.on("data", function (data) {
           buf = Buffer.concat([buf, data]);
         });
         /** Finish receiving the data blocks. Generate a DOMString */
         file.on("end", function () {
           const imgBase64 = buf.toString("base64");
           html += `<img src="data:${mimetype};base64, ${imgBase64}" />`;
         });
       });
       /** Finish receiving multipart/form-data. Construct and return the generated HTML */
       busboy.on("finish", function () {
         console.log({ msg: "Parse form complete!", html });
         resolve({
           statusCode: 200,
           headers: {
             "content-type": "text/html",
           },
           body: html,
         });
       });
      
       /**
        * busboy needs to be processed using the stream pipe method.
        * After the body is decoded into a buffer,
        * Convert it into a stream and pipe it to busboy
        */
       const bodyBuf = Buffer.from(event.body, "base64");
       var bufferStream = new stream.PassThrough();
       bufferStream.end(bodyBuf);
       bufferStream.pipe(busboy);
      });
      };
      
      /** Return the static file */
      const handleGet = (event) => {
      const html = `<html><head></head><body>
       <form method="POST" enctype="multipart/form-data">
       <input type="file" name="image-1" accept="image/*"><br />
        <input type="file" name="image-2" accept="image/*"><br />
        <input type="submit">
       </form>
       </body></html>`;
      console.log({ msg: "Get form complete!", html });
      return {
       statusCode: 200,
       headers: {
         "content-type": "text/html",
       },
       body: html,
      };
      };
      
      /** Entry function for SCF */
      exports.main_handler = async (event, context) => {
      const method = event.httpMethod;
      /** For POST requests, process the user’s multipart/form-data and generate the page that displays the upload effect */
      if (method === "POST") {
       return handlePost(event);
      }
      /** For GET requests, return the page that is used for file upload */
      if (method === "GET") {
       return handleGet(event);
      }
      };
    1. After writing the code, you can install the dependencies for SCF. For example, you can use busboy to decode the data of multipart/form-data.

      Note:

      Dependencies need to be installed in the src directory.

    2. Click Deploy.

    Step 3. Bind the API Gateway trigger

    To process the user’s specific HTTP requests, we need to bind an API Gateway trigger to your cloud function on the Trigger Management page of your cloud function in SCF. The following figure shows how to bind it and the corresponding configurations:

    In this case, if you access the URL bound with API Gateway, you can see that though the static website can work, the desired page is not displayed after you uploaded an image. The cause is that the Base64 encoding feature of API Gateway is disabled by default. Therefore, multipart/form-data that is wrongly encoded into a string and passed to the handler function cannot be decoded by busboy.

    To solve this, you can log in to API Gateway, find the bound API service, and enable Base64 Encoding for it in Basic Configurations.

    After you open and publish the service, the service can work properly.

    Demo

    You can view the file upload effects by visiting the Demo set up by Tencent Cloud Serverless.

    Was this page helpful?

    Was this page helpful?

    • Not at all
    • Not very helpful
    • Somewhat helpful
    • Very helpful
    • Extremely helpful
    Send Feedback
    Help