generating and serving static files with Meteor generating and serving static files with Meteor express express

generating and serving static files with Meteor


In version 0.6.6.3 0.7.x - 1.3.x you can do the following:

To write

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

To serve

In vanilla meteor app

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

When using iron:router

This should be a server side route (ex: defined in a file in /server/ folder)

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

Outdated format:

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

Notes

  • process.env.PWD will give you the project root
  • if you plan to put files inside your project

    • don't use the public or private meteor folders
    • use dot folders (eg. hidden folders ex: .uploads)

    Not respecting these two will cause local meteor to restart on every upload, unless you run your meteor app with: meteor run --production

  • I've used this approach for a simple image upload & serve (based on dario's version)
  • Should you wish for more complex file management please consider CollectionFS


The symlink hack will no longer work in Meteor (from 0.6.5). Instead I suggest creating a package with similar code to the following:

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 requestsWebApp.connectHandlers  .use('/my-uploaded-content', connect.static(process.env['APP_DYN_CONTENT_DIR']));


I was stuck at the exact same problem, where i need the users to upload files in contrast to your server generated files. I solved it sort of by creating an "uploads" folder as sibling to the "client public server" on the same folder level. and then i created a simbolic link to the '.meteor/local/build/static' folder like

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

but with nodejs filesystem api at server start time

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

in your case you may have a folder like "generatedFiles" instead of my "uploads" folderyou need to do this every time the server starts up cuz these folders are generated every time the server starts up e.g. a file changes in your implementation.