Générant et servant des fichiers statiques avec Meteor

Je cherche à créer des fichiers texte statiques en fonction du contenu d'un objet fourni, qui peut ensuite être téléchargé par l'utilisateur. Voici ce que je prévoyais faire:

  1. Lorsque l'utilisateur frappe 'exporter', l'application appelle un Meteor.method() qui, à son tour, analyse et écrit le fichier dans le répertoire public en utilisant des méthodes de nœud typiques.

  2. Une fois le fichier créé, dans le rappel de Meteor.method() je fournit un lien vers le fichier généré. Par exemple, 'public / userId / file.txt'. L'utilisateur peut alors choisir de télécharger le fichier sur ce lien.

  3. J'utilise ensuite Meteor's Connect modele (qu'il utilise en interne) pour acheminer toutes les requêtes vers l'URL ci-dessus vers le fichier lui-même. Je pourrais faire des vérifications d'autorisations en fonction de l'utilisateur et de l'état connecté de l'utilisateur.

Le problème: lorsque les fichiers statiques sont générés en public, la page Web se recharge automatiquement à chaque fois. Je pensais qu'il serait plus logique d'utiliser quelque chose comme Express pour générer un point final REST, qui pourrait traiter la création des fichiers. Mais je ne suis pas sûr de savoir comment traiter les autorisations si je n'ai pas accès aux données de la session Meteor.

Des idées sur la meilleure stratégie ici?

Le lien symbolique ne fonctionnera plus dans Meteor (à partir de 0.6.5). Au lieu de cela, je suggère de créer un package avec un code similaire à celui-ci:

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

En version 0.6.6.3 0.7.x1.3.x vous pouvez faire ce qui suit:

Écrire

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

Servir

Dans l'application de météorite vanille

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

Lors de l'utilisation du fer: routeur

Il doit s'agir d'une route côté serveur (ex: définie dans un fichier dans /server/ folder)

Modifier (2016-mai-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(); } }); 

Format dépassé:

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

Remarques

  • process.env.PWD vous donnera la racine du projet
  • Si vous prévoyez de mettre des fichiers dans votre projet

    • N'utilisez pas les dossiers de météores public ou private
    • Utiliser des dossiers de points (p. Ex. Dossiers cachés ex: .uploads )

    Ne pas respecter ces deux causes provoqueront des météorites locaux à recommencer à chaque téléchargement, sauf si vous exécutez votre application de météorite avec: production de meteor run --production

  • J'ai utilisé cette approche pour un simple téléchargement et chargement d'images (basé sur la version de dario )
  • Si vous souhaitez une gestion de fichier plus complexe, veuillez considérer CollectionFS

J'ai été coincé au même problème, où j'ai besoin que les utilisateurs téléchargent des fichiers en contraste avec vos fichiers générés par le serveur. Je l'ai résolu en créant un dossier "uploads" en tant que frère et sœur au "serveur public client" sur le même niveau de dossier. Et puis j'ai créé un lien simbolique vers le dossier '.meteor / local / build / static' comme

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

Mais avec le système de fichiers nodejs api à l'heure de début du serveur

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

Dans votre cas, vous pouvez avoir un dossier comme "fichiers générés" au lieu de mon dossier "télécharger", vous devez le faire chaque fois que le serveur démarre, ces dossiers sont générés chaque fois que le serveur démarre, par exemple, un fichier change dans votre implémentation.

Une autre option consiste à utiliser une voie côté serveur pour générer le contenu et l'envoyer au navigateur de l'utilisateur pour téléchargement. Par exemple, le suivant recherchera un utilisateur par ID et le renverra comme JSON. L'utilisateur final est invité à enregistrer la réponse dans un fichier avec le nom spécifié dans l'en-tête Content-Disposition. D'autres en-têtes, tels que Expires, pourraient également être ajoutés à la réponse. Si l'utilisateur n'existe pas, un 404 est renvoyé.

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

Cette méthode a toutefois un gros inconvénient. Les routes côté serveur ne fournissent pas un moyen simple d'accéder à l'utilisateur actuellement connecté. Voir ce problème sur GitHub .