Make ember cli serve uploaded files

26 Mar 2015

I currently work on a projet with a backend in Go and a web app powered by Ember.js with an image upload feature.

When developing, I use the server provided by ember cli with a proxy enabled to send api requests to my backend:

$ ember server --proxy http://127.0.0.1:<BACKEND_PORT>

All requests starting with /api are proxied to the backend, and the ember cli server serves the ember app files and the assets, with a nice live-reload feature. This setup is perfect for development.

However, how to handle uploaded files ? My backend needs to store them somewhere on the file system where the ember cli server can serves them too.

You may think that storing them inside the /public directory of the ember cli project is the solution. But this is not the way to go, because everything in the /public folder is copied into the /dist directory when building your app, including for production. So that's a bad idea.

I searched how to make the ember cli server serve another directory. I'm not sure this is the best way to do it, but here is the solution I came to.

First let's create the upload directory in the ember cli project:

$ cd myapp
$ mkdir upload

Add a /upload/test.html file with this content:

This file is in the upload directory

Now let's generate a server directory:

$ ember g server

ember g server

The main purpose of the new server directory is to mock server enpoints.

Open the /server/index.js file and add those lines:

var express = require('express');
app.use('/upload', express.static(__dirname + "/../upload"));

For example, my file looks like that:

// To use it create some files under `mocks/`
// e.g. `server/mocks/ember-hamsters.js`
//
// module.exports = function(app) {
//   app.get('/ember-hamsters', function(req, res) {
//     res.send('hello');
//   });
// };

module.exports = function(app) {
  var globSync   = require('glob').sync;
  var mocks      = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require);
  var proxies    = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require);

  // Log proxy requests
  var morgan  = require('morgan');
  app.use(morgan('dev'));

  mocks.forEach(function(route) { route(app); });
  proxies.forEach(function(route) { route(app); });

  // Permits to serve files in /upload directory
  var express = require('express');
  app.use('/upload', express.static(__dirname + "/../upload"));
};

Adds express dependency:

$ npm install express --save-dev

Start the server:

$ ember server

And now browse to: http://127.0.0.1:4200/upload/test.html

serving upload dir

Victory \o/

My backend can now save uploaded file into the /upload directory of my ember cli project, and the ember cli server will serve them.

victory

You can now continue having fun with Ember.js.

@aymerick