que lightroom importar contenido archivos archivo loopbackjs strongloop

loopbackjs - contenido - importar archivo xmp lightroom



¿Cómo almacenar archivos con metadatos en LoopBack? (7)

Aquí está la solución completa para almacenar metadatos con archivos en loopback.

Necesitas un modelo de contenedor

common/models/container.json

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

Crea la fuente de datos para tu contenedor en server/datasources.json . Por ejemplo:

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

Necesitará configurar la fuente de datos de este modelo en server/model-config.json para el loopback-component-storage que tiene:

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

También necesitará un modelo de archivo para almacenar los metadatos y manejar llamadas a contenedores:

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": [] }

Y ahora conecta files con 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''} } ); };

Para exponer los archivos api, agregue al archivo model-config.json el modelo de files , recuerde seleccionar sus model-config.json datos correctas:

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

¡Hecho! Ahora puede llamar a POST /api/files/upload con un archivo de datos binarios en file campo de formulario de file . A cambio, recibirá la identificación, el nombre, el tipo y la URL.

Lo que quiero hacer: tener un formulario html, con una entrada de archivo dentro. Cuando se elige un archivo, la entrada de archivo debe cargar el archivo y obtener una identificación de archivo, de modo que cuando se envíe el formulario, la identificación del archivo se publique con el formulario y se escriba en la base de datos.

Versión más corta: quiero almacenar metadatos (identificación por ejemplo) con mis archivos.

Suena simple, pero me cuesta hacer eso en LoopBack.

Hubo un par de conversaciones ( 1 , 2 ) sobre este tema, y ​​ninguna parecía conducir a una solución, así que pensé que este podría ser un buen lugar para encontrar una vez.

La solución más simple sería usar relaciones modelo, pero LoopBack no admite relaciones con el servicio de almacenamiento de archivos. Bache. Así que tenemos que ir con un modelo persistente llamado File por ejemplo, y anular la creación predeterminada, eliminar para que se guarde y elimine del modelo de la tienda de archivos que tengo, llamado Storage .

Mi configuración hasta ahora:

  • Tengo un modelo / api / Storage que está conectado a un servicio de almacenamiento en loopback y está guardando el archivo exitosamente en el sistema de archivos local.
  • Tengo un modelo PersistedModel conectado a Mongo con metadatos de archivos: name , size , url y objectId
  • Tengo un enganche remoto configurado antes de create para que el archivo pueda guardarse primero y luego su url se puede inyectar en File.create()

Estoy allí, y de acuerdo con esta página de LoopBack , tengo el ctx que debería tener el archivo dentro:

File.beforeRemote(''create'', function(ctx, affectedModelInstance, next) {})`

¿Qué es ctx ?

ctx.req : objeto de solicitud expresa.
ctx.result : Express Response object.

Ok, ahora estoy en la página Express, bastante perdido, y se trata de un "middleware de análisis del cuerpo" que no tengo ni idea de lo que podría ser.

Siento que estoy cerca de la solución, cualquier ayuda sería apreciada . ¿Es este enfoque correcto?


Dependiendo de su escenario, puede valer la pena utilizar firmas o similares que permitan cargas directas a Amazon S3, TransloadIT (para el procesamiento de imágenes) o servicios similares.

Nuestra primera decisión con este concepto fue que, como utilizamos GraphQL, queríamos evitar la carga de formas multiparte a través de GraphQL, que a su vez tendría que transferirse a nuestros servicios de Loopback. Además, queríamos mantener estos servidores eficientes sin potencialmente vincular recursos con cargas (grandes) y validación y procesamiento de archivos asociados.

Su flujo de trabajo puede verse más o menos así:

  1. Crear registro de base de datos
  2. Devuelva la identificación de registro y los datos de firma de carga de archivo (incluye el depósito S3 o el punto final TransloadIT, más los tokens de autenticación)
  3. Cliente sube al punto final

Para los casos en los que hacer cosas como carga de banner o avatar, el paso 1 ya existe, omitamos ese paso.

Además, puede agregar notificaciones SNS o SQS a sus depósitos S3 para confirmar en su base de datos que el objeto relevante ahora tiene un archivo adjunto, de hecho, el Paso 4.

Este es un proceso de varios pasos, pero puede funcionar bien eliminando la necesidad de manejar las cargas de archivos dentro de su API principal. Hasta ahora, esto está funcionando bien desde nuestra implementación inicial (primeros días en este proyecto) para cosas como avatares de usuario y adjuntar archivos PDF a un registro.

Referencias de ejemplo:

http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingHTTPPOST.html

https://transloadit.com/docs/#authentication


Para aquellos que buscan una respuesta a la pregunta "cómo verificar el formato de archivo antes de subir un archivo" .

Actual en este caso podemos usar el parámetro opcional permitidoContentTypes .

En el arranque del directorio use un código de ejemplo:

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

Espero que ayude a alguien.


Para cualquier otra persona que tenga ese problema con loopback 3 y Postman que en POST, la conexión se cuelga (o devuelve ERR_EMPTY_RESPONSE) (se ve en algunos comentarios aquí) ... El problema en este escenario es que Postman utiliza como tipo de contenido "application / x-www-form-urlencoded "!

Elimine ese encabezado y agregue "Aceptar" = "multipart / form-data". Ya he archivado un error en loopback por este comportamiento


Para usuarios de SDK de AngularJS ... En caso de que desee utilizar métodos generados como Container.upload (), es posible que desee agregar una línea para configurar el método en lb-services.js para establecer los encabezados Content-Type en undefined . Esto permitiría al cliente establecer encabezados de tipo de contenido y agregar valor de límite automáticamente. Se vería algo como esto:

"upload": { url: urlBase + "/containers/:container/upload", method: "POST", headers: {"Content-Type": undefined} }


Simplemente pase los datos como un objeto "params" y en el servidor puede obtenerlo como ctx.req.query

Por ejemplo

En el lado del cliente

Upload.upload( { url: ''/api/containers/container_name/upload'', file: file, //Additional data with file params:{ orderId: 1, customerId: 1, otherImageInfo:[] } });

En el lado del servidor

Supongamos que su nombre de modelo de almacenamiento es container

Container.beforeRemote(''upload'', function(ctx, modelInstance, next) { //OUPTUTS: {orderId:1, customerId:1, otherImageInfo:[]} console.log(ctx.req.query); next(); })


Yo tuve el mismo problema. Lo resolví creando mis propios modelos para almacenar metadatos y mis propios métodos de carga.

  1. Creé un modelo de File que almacenará información como nombre, tipo, url, userId (igual que el tuyo)

  2. Creé mi propio método de carga remota porque no pude hacerlo con los ganchos. El modelo de contenedor es el modelo creado por loopback-component-storage .

  3. var fileInfo = fileObj.files.myFile[0]; Aquí myFile es el nombre de campo para la carga de archivos, por lo que deberá cambiarlo en consecuencia. Si no especifica ningún campo, vendrá como fileObj.file.null[0] . Este código carece de la comprobación de errores adecuada, hágalo antes de implementarlo en producción .

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