total sails adonisjs javascript express meteor

javascript - sails - generando y sirviendo archivos estáticos con Meteor



sails vs express (4)

El hack del enlace simbólico ya no funcionará en Meteor (desde 0.6.5). En su lugar, sugiero crear un paquete con un código similar al siguiente:

packge.js

Package.describe({ summary: "Application file server." }); Npm.depends({ connect: "2.7.10" }); Package.on_use(function(api) { api.use([''webapp'', ''routepolicy''], ''server''); api.add_files([ ''app-file-server.js'', ], ''server''); });

app-file-server.js

var connect = Npm.require(''connect''); RoutePolicy.declare(''/my-uploaded-content'', ''network''); // Listen to incoming http requests WebApp.connectHandlers .use(''/my-uploaded-content'', connect.static(process.env[''APP_DYN_CONTENT_DIR'']));

Estoy buscando crear archivos de texto estático basados ​​en el contenido de un objeto suministrado, que luego puede ser descargado por el usuario. Esto es lo que planeaba hacer:

  1. Cuando el usuario hace Meteor.method() "exportar", la aplicación llama a Meteor.method() que, a su vez, analiza y escribe el archivo en el directorio público utilizando métodos típicos de Nodo.

  2. Una vez que se crea el archivo, en la devolución de llamada de Meteor.method() proporciono un enlace al archivo generado. Por ejemplo, ''public / userId / file.txt''. El usuario puede elegir descargar el archivo en ese enlace.

  3. Luego utilizo el Connect modele (que usa internamente) para dirigir cualquier solicitud a la URL anterior al archivo en sí. Podría hacer una verificación de permisos basada en el ID de usuario y el estado de inicio de sesión del usuario.

El problema: cuando los archivos estáticos se generan en público, la página web se vuelve a cargar automáticamente cada vez. Pensé que podría tener más sentido utilizar algo como Express para generar un punto final REST, que podría tratar de crear los archivos. Pero entonces no estoy seguro de cómo tratar con los permisos si no tengo acceso a los datos de la sesión de Meteor.

¿Alguna idea sobre la mejor estrategia aquí?


En version 0.6.6.3 0.7.x - 1.3.x puedes hacer lo siguiente:

Escribir

var fs = Npm.require(''fs''); var filePath = process.env.PWD + ''/.uploads_dir_on_server/'' + fileName; fs.writeFileSync(filePath, data, ''binary'');

Servir

En la aplicación de meteoros de vainilla

var fs = Npm.require(''fs''); WebApp.connectHandlers.use(function(req, res, next) { var re = /^//uploads_url_prefix//(.*)$/.exec(req.url); if (re !== null) { // Only handle URLs that start with /uploads_url_prefix/* var filePath = process.env.PWD + ''/.uploads_dir_on_server/'' + re[1]; var data = fs.readFileSync(filePath); res.writeHead(200, { ''Content-Type'': ''image'' }); res.write(data); res.end(); } else { // Other urls will have default behaviors next(); } });

Al usar hierro: enrutador

Esta debe ser una ruta del lado del servidor (por ejemplo, definida en un archivo en /server/ folder)

Editar (2016-Mayo-9)

var fs = Npm.require(''fs''); Router.route(''uploads'', { name: ''uploads'', path: /^//uploads_url_prefix//(.*)$/, where: ''server'', action: function() { var filePath = process.env.PWD + ''/.uploads_dir_on_server/'' + this.params[0]; var data = fs.readFileSync(filePath); this.response.writeHead(200, { ''Content-Type'': ''image'' }); this.response.write(data); this.response.end(); } });

Formato obsoleto:

Router.map(function() { this.route(''serverFile'', { ...// same as object above } });

Notas

  • process.env.PWD te dará la raíz del proyecto
  • Si planeas poner archivos dentro de tu proyecto.

    • No uses las carpetas de meteoros public o private
    • usar carpetas de puntos (por ejemplo, carpetas ocultas ex: .uploads )

    No respetar estos dos hará que el meteorito local se reinicie en cada carga, a menos que ejecute su aplicación de meteorito con: meteor run --production

  • He utilizado este enfoque para una carga y servicio de imágenes simple (basado en la versión de dario )
  • Si desea una gestión de archivos más compleja, considere CollectionFS

Me quedé atascado en el mismo problema, donde necesito que los usuarios carguen archivos en contraste con los archivos generados por el servidor. Resolví el problema creando una carpeta de "cargas" como hermanos en el "servidor público del cliente" en el mismo nivel de carpeta. y luego creé un enlace simbólico a la carpeta ''.meteor / local / build / static'' como

ln -s ../../../../uploads .meteor/local/build/static/

pero con la API del sistema de archivos nodejs a la hora de inicio del servidor

Meteor.startup(function () { var fs = Npm.require(''fs''); fs.symlinkSync(''../../../../uploads'', ''.meteor/local/build/static/uploads''); };

en su caso, puede tener una carpeta como "genericFiles" en lugar de mi carpeta "uploads" que necesita hacer esto cada vez que el servidor se inicia, porque estas carpetas se generan cada vez que el servidor se inicia, por ejemplo, un archivo cambia en su implementación.


Otra opción es utilizar una ruta del lado del servidor para generar el contenido y enviarlo al navegador del usuario para su descarga. Por ejemplo, lo siguiente buscará un usuario por ID y lo devolverá como JSON. Se le pide al usuario final que guarde la respuesta en un archivo con el nombre especificado en el encabezado Content-Disposition. Otros encabezados, como Expires, también podrían agregarse a la respuesta. Si el usuario no existe, se devuelve un 404.

Router.route("userJson", { where: "server", path: "/user-json/:userId", action: function() { var user = Meteor.users.findOne({ _id: this.params.userId }); if (!user) { this.response.writeHead(404); this.response.end("User not found"); return; } this.response.writeHead(200, { "Content-Type": "application/json", "Content-Disposition": "attachment; filename=user-" + user._id + ".json" }); this.response.end(JSON.stringify(user)); } });

Sin embargo, este método tiene un gran inconveniente. Las rutas del lado del servidor no proporcionan una manera fácil de obtener el usuario que ha iniciado sesión actualmente. Vea este tema en GitHub .