如何在LoopBack中存储带有元数据的文件?

Mih*_* KR 47 strongloop loopbackjs

我想做什么:有一个html表单,里面有文件输入.选择文件时,文件输入应上传文件,并获取文件ID,因此在提交表单时,文件ID将与表单一起发布并写入数据库.

更短的版本:我想用我的文件存储元数据(例如id).

听起来很简单,但我很难在LoopBack中做到这一点.

已经有一对夫妇的谈话(1,2)这个话题,既不似乎导致一个解决方案,所以我想这可能是找到一个一劳永逸的好地方.

最简单的解决方案是使用模型关系,但LoopBack不支持与文件存储服务的关系.凹凸.因此我们必须使用以File示例命名的persistedmodel ,并覆盖默认的create,delete,以便从我命名的文件存储模型中保存和删除Storage.

到目前为止我的设置:

  • 我有一个模型/ api/Storage连接到环回存储服务,并将文件成功保存到本地文件系统.
  • 我有连接到蒙戈与文件元数据的PersistedModel: ,,namesizeurlobjectId
  • 我之前设置了一个远程钩子,create因此可以先保存文件,然后将url其注入File.create()

我在那里,根据这个LoopBack页面,我有ctx,里面应该有文件:

File.beforeRemote('create', function(ctx, affectedModelInstance, next) {})`
Run Code Online (Sandbox Code Playgroud)

什么ctx

ctx.req:Express Request对象.
ctx.result:快速响应对象.

好的,所以现在我在Express页面上,非常迷失,这就是一个关于'正在解析的中间件'的东西,我不知道它可能是什么.

我觉得我很接近解决方案,任何帮助将不胜感激.这种方法对吗?

Mih*_* KR 56

这是使用环回文件存储元数据的完整解决方案.

你需要一个容器模型

common/models/container.json

{
  "name": "container",
  "base": "Model",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {},
  "validations": [],
  "relations": {},
  "acls": [],
  "methods": []
}
Run Code Online (Sandbox Code Playgroud)

在中创建容器的数据源server/datasources.json.例如:

...
"storage": {
    "name": "storage",
    "connector": "loopback-component-storage",
    "provider": "filesystem", 
    "root": "/var/www/storage",
    "maxFileSize": "52428800"
}
...
Run Code Online (Sandbox Code Playgroud)

你需要这个模型的数据源设置server/model-config.jsonloopback-component-storage你有:

...
"container": {
    "dataSource": "storage",
    "public": true
}
...
Run Code Online (Sandbox Code Playgroud)

您还需要一个文件模型来存储元数据并处理容器调用:

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": []
}
Run Code Online (Sandbox Code Playgroud)

现在连接filescontainer:

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

};
Run Code Online (Sandbox Code Playgroud)

为了公开文件api添加到模型model-config.json文件中files,请记住选择正确的数据源:

...
"files": {
    "dataSource": "db",
    "public": true
}
...
Run Code Online (Sandbox Code Playgroud)

完成!您现在可以/api/files/uploadfile表单字段中使用文件二进制数据调用POST .您将获得返回的id,名称,类型和URL.

  • 上面的配置给我.`('不能覆盖内置的"{{file}}"类型.'));` (2认同)

Har*_*dhi 10

我有同样的问题.我通过创建自己的模型来存储元数据和我自己的上传方法来解决它.

  1. 我创建了一个模型File,它将存储信息,如名称,类型,网址,userId(与您的相同)

  2. 我创建了自己的上传远程方法,因为我无法使用钩子.容器模型是由loopback-component-storage创建的模型.

  3. var fileInfo = fileObj.files.myFile[0];这里myFile是文件上传的字段名,因此您必须相应地更改它.如果你没有指定任何字段,那么它将成为fileObj.file.null[0]. 此代码缺少正确的错误检查,在将其部署到生产环境之前执行此操作.

     File.uploadFile = function (ctx,options,cb) {
      File.app.models.container.upload(ctx.req,ctx.result,options,function (err,fileObj) {
        if(err) cb(err);
        else{
                // Here myFile is the field name associated with upload. You should change it to something else if you
                var fileInfo = fileObj.files.myFile[0];
                File.create({
                  name: fileInfo.name,
                  type: fileInfo.type,
                  container: fileInfo.container,
                  userId: ctx.req.accessToken.userId,
                  url: CONTAINERS_URL+fileInfo.container+'/download/'+fileInfo.name // This is a hack for creating links
                },function (err,obj) {
                  if(err){
                    console.log('Error in uploading' + err);
                    cb(err);
                  }
                  else{
                    cb(null,obj);
                  }
                });
              }
            });
    };
    
    File.remoteMethod(
      'uploadFile',
      {
        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'}
      }
    
    );
    
    Run Code Online (Sandbox Code Playgroud)


小智 8

对于那些正在寻找"如何在上传文件之前检查文件格式"这一问题的答案的人.

在这种情况下,我们可以使用可选的param allowedContentTypes.

在目录启动中使用示例代码:

module.exports = function(server) {
    server.dataSources.filestorage.connector.allowedContentTypes = ["image/jpg", "image/jpeg", "image/png"];
}
Run Code Online (Sandbox Code Playgroud)

我希望它能帮助别人.