How to store files with meta data in LoopBack?

前端 未结 7 1733
别跟我提以往
别跟我提以往 2020-11-28 03:05

What I want to do: Have an html form, with a file input inside. When a file is chosen, the file input should upload the file, and get a file id, so when the form is submitte

7条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-28 03:45

    Here's the full solution for storing meta data with files in loopback.

    You need a container model

    common/models/container.json

    {
      "name": "container",
      "base": "Model",
      "idInjection": true,
      "options": {
        "validateUpsert": true
      },
      "properties": {},
      "validations": [],
      "relations": {},
      "acls": [],
      "methods": []
    }
    

    Create the data source for your container in server/datasources.json. For example:

    ...
    "storage": {
        "name": "storage",
        "connector": "loopback-component-storage",
        "provider": "filesystem", 
        "root": "/var/www/storage",
        "maxFileSize": "52428800"
    }
    ...
    

    You'll need to set the data source of this model in server/model-config.json to the loopback-component-storage you have:

    ...
    "container": {
        "dataSource": "storage",
        "public": true
    }
    ...
    

    You'll also need a file model to store the meta data and handle container calls:

    common/models/files.json

    {
      "name": "files",
      "base": "PersistedModel",
      "idInjection": true,
      "options": {
        "validateUpsert": true
      },
      "properties": {
        "name": {
          "type": "string"
        },
        "type": {
          "type": "string"
        },
        "url": {
          "type": "string",
          "required": true
        }
      },
      "validations": [],
      "relations": {},
      "acls": [],
      "methods": []
    }
    

    And now connect files with container:

    common/models/files.js

    var CONTAINERS_URL = '/api/containers/';
    module.exports = function(Files) {
    
        Files.upload = function (ctx,options,cb) {
            if(!options) options = {};
            ctx.req.params.container = 'common';
            Files.app.models.container.upload(ctx.req,ctx.result,options,function (err,fileObj) {
                if(err) {
                    cb(err);
                } else {
                    var fileInfo = fileObj.files.file[0];
                    Files.create({
                        name: fileInfo.name,
                        type: fileInfo.type,
                        container: fileInfo.container,
                        url: CONTAINERS_URL+fileInfo.container+'/download/'+fileInfo.name
                    },function (err,obj) {
                        if (err !== null) {
                            cb(err);
                        } else {
                            cb(null, obj);
                        }
                    });
                }
            });
        };
    
        Files.remoteMethod(
            'upload',
            {
                description: 'Uploads a file',
                accepts: [
                    { arg: 'ctx', type: 'object', http: { source:'context' } },
                    { arg: 'options', type: 'object', http:{ source: 'query'} }
                ],
                returns: {
                    arg: 'fileObject', type: 'object', root: true
                },
                http: {verb: 'post'}
            }
        );
    
    };
    

    For expose the files api add to the model-config.json file the files model, remember select your correct datasources:

    ...
    "files": {
        "dataSource": "db",
        "public": true
    }
    ...
    

    Done! You can now call POST /api/files/upload with a file binary data in file form field. You'll get back id, name, type, and url in return.

提交回复
热议问题