Search code examples
node.jstypescriptmongodbgridfsloopback4

How can i upload to MongoDB GridFS from loopback 4


I'am new to Loopback 4. I was trying to upload files using loopback 4 to MongoDB GridFS. I used the file upload example from Loopback 4 examples but couldn't understand it enough to modify it?

protected configureFileUpload(destination?: string) {
    const url = 'mongodb://' + MongoDataSource.defaultConfig.user + ':' +
      MongoDataSource.defaultConfig.password
      + '@' + MongoDataSource.defaultConfig.host +
      ':' + MongoDataSource.defaultConfig.port +
      '/' + MongoDataSource.defaultConfig.database;
    const conn = mongoose.createConnection(url);
    let gfs;
    conn.once('open', () => {
      gfs = Grid(conn.db, mongoose.mongo);
      gfs.collection('uploads');
    });

    const storage = new GridFsStorage({
      url: url,
      file: (req: any, file: any) => {
        return new Promise((resolve, reject) => {
          //crypto create a unique id for the file to be uploaded
          crypto.randomBytes(16, (err, buf) => {
            if (err) return reject(err);
            const filename = buf.toString('hex') + path.extname(file.originalname);
            const fileInfo = {
              filename: filename,
              bucketName: 'bucketName',
              metadata: {
                originalName: file.originalname,
                encoding: file.encoding,
                mimetype: file.mimetype,
                size: file.size,
                expires: Date.now() + 1000 * 60 * 60
              }
            }
            resolve(fileInfo)
          })
        });
      }
    });
    storage;

    return multer({storage: storage}).any();
  }

Solution

  • This how I solved my own problem

    import {inject} from '@loopback/core';
    import {
      repository
    } from '@loopback/repository';
    import {
      getModelSchemaRef,
      post,
      Request,
      requestBody,
      Response,
      response,
      RestBindings
    } from '@loopback/rest';
    import crypto from 'crypto';
    import multer from 'multer';
    import {GridFsStorage} from 'multer-gridfs-storage';
    import path from 'path';
    import {MongoDataSource} from '../datasources';
    import {FILE_UPLOAD_SERVICE} from '../keys';
    import {Gridfs} from '../models';
    import {GridfsRepository} from '../repositories';
    import {FileUploadHandler} from '../types';
    
    const url = 'mongodb://' + MongoDataSource.defaultConfig.user +
      ':' + MongoDataSource.defaultConfig.password +
      '@' + MongoDataSource.defaultConfig.host +
      ':' + MongoDataSource.defaultConfig.port +
      '/' + MongoDataSource.defaultConfig.database;
    
    var storage = new GridFsStorage({
      url: url,
      file: (req: any, file: any) => {
        return new Promise((resolve, reject) => {
          //crypto create a unique id for the file to be uploaded
          crypto.randomBytes(16, (err, buf) => {
            if (err) return reject(err);
            const filename = buf.toString('hex') + path.extname(file.originalname);
            const fileInfo = {
              filename: filename,
              bucketName: 'documents',
              metadata: {
                originalName: file.originalname,
                encoding: file.encoding,
                mimetype: file.mimetype,
                size: file.size,
                expires: Date.now() + 1000 * 60 * 60
              }
            }
            return resolve(fileInfo)
          })
        });
      }
    });
    const upload = multer({storage});
    
    export class GridfsController {
      constructor(
        @repository(GridfsRepository)
        public gridfsRepository: GridfsRepository,
        @inject(FILE_UPLOAD_SERVICE) private handler: FileUploadHandler,
      ) {
        console.log(FILE_UPLOAD_SERVICE);
        console.log(handler);
      }
    
      @post('/gridfs')
      @response(200, {
        description: 'Tender model instance',
        content: {'multipart/form-data': {schema: getModelSchemaRef(Gridfs)}},
      })
      async create(
        @requestBody({
          content: {
            'multipart/form-data': {
              schema: getModelSchemaRef(Gridfs, {
                title: 'NewGridfs',
                exclude: ['id'],
              }),
            },
          },
        })
        gridfs: Omit<Gridfs, 'id'>,
      ): Promise<Gridfs> {
        return this.gridfsRepository.create(gridfs);
      }
    
      @post('/files', {
        responses: {
          200: {
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                },
              },
            },
            description: 'Files and fields',
          },
        },
      })
      async fileUpload(
        @requestBody.file()
        request: Request,
        @inject(RestBindings.Http.RESPONSE) response: Response,
      ): Promise<object> {
        return new Promise<object>((resolve, reject) => {
          upload.single('file')(request, response, err => {
            if (err) return reject(err);
            let file = request.file as any;
            resolve({
              id: file.id.toString(),
              originalName: file.originalname,
              encoding: file.encoding,
              mimetype: file.mimetype,
              size: file.size,
              expires: Date.now() + 1000 * 60 * 60
            });
          });
        });
      }
    }
    

    Apparently it's so much easy