Harsha Vardhan
Harsha Vardhan

Reputation: 21

Loopback4 File upload Storage component Example

I’m looking for an example for a file store using loopback4, could someone provide the controller configuration for file crud operations?

Upvotes: 1

Views: 1441

Answers (1)

Miroslav Bajtoš
Miroslav Bajtoš

Reputation: 10785

LoopBack 4 does not provide a built-in parser for multipart file upload requests. Instead, we provide extension points allowing applications to use a 3rd party parsers like multer.

There are two options how to write a controller accepting file uploads. You can learn more about this topic in our docs, see Parsing requests and Extending request body parsing

1. Handle file uploads in the controller method

Instruct LoopBack to pass the raw body stream to your controller method. In the controller method, call the file-upload parser to process the multi-part stream.

Benefits: different endpoints may want to process the uploaded files differently. By implementing file-upload parsing in a controller method, it's easy to customize all aspects of this process.

Cross-posting an example from file-upload.acceptance.ts:

import * as multer from 'multer';

class FileUploadController {
  @post('/show-body', {
    responses: {
      // (left out for brevity)
    },
  })
  async showBody(
    @requestBody({
      description: 'multipart/form-data value.',
      required: true,
      content: {
        'multipart/form-data': {
          // Skip body parsing
          'x-parser': 'stream',
          schema: {type: 'object'},
        },
      },
    })
    request: Request,
    @inject(RestBindings.Http.RESPONSE) response: Response,
  ): Promise<Object> {
    const storage = multer.memoryStorage();
    const upload = multer({storage});
    return new Promise<object>((resolve, reject) => {
      upload.any()(request, response, err => {
        if (err) reject(err);
        else {
          resolve({
            files: request.files,
            fields: (request as any).fields,
          });
        }
      });
    });
  }

2. Implement & register a body parser for multi-part file uploads

In this option, all file-uploads are processed at transport layer in the same way for all controller methods. Controller methods receive parsed data.

Example body parser implementation from file-upload-with-parser.acceptance.ts:

class MultipartFormDataBodyParser implements BodyParser {
  name = 'multipart/form-data';

  supports(mediaType: string) {
    // The mediaType can be
    // `multipart/form-data; boundary=--------------------------979177593423179356726653`
    return mediaType.startsWith('multipart/form-data');
  }

  async parse(request: Request): Promise<RequestBody> {
    const storage = multer.memoryStorage();
    const upload = multer({storage});
    return new Promise<RequestBody>((resolve, reject) => {
      upload.any()(request, {} as any, err => {
        if (err) reject(err);
        else {
          resolve({
            value: {
              files: request.files,
              fields: (request as any).fields,
            },
          });
        }
      });
    });
  }
}

An example controller leveraging this body parser:

class FileUploadController {
  @post('/show-body', {
    responses: {
      // (left out for brevity)
    },
  })
  async showBody(
    @requestBody({
      description: 'multipart/form-data value.',
      required: true,
      content: {
        'multipart/form-data': {
          schema: {type: 'object'},
        },
      },
    })
    {files, fields}: any,
  ) {
    return body;
  }
}

Upvotes: 3

Related Questions