node.jsexpressfile-uploadnode.js-connect

How can I upload a file using Node.js?


I've already seen Uploading images using Node.js, Express, and Mongoose but I'm using an MVC architecture with ExpressJS. In my app.coffee, I'm doing:

app.configure(function() {
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(form({
    keepExtensions: true
  }));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser());
  app.use(express.session(sessionVariables));
  app.use(app.router);
  return app.use(express.static(__dirname + '/public'));
});

And in my controller method, I'm doing:

exports.uploadCustomersApi = function(req, res) {
  return console.log(req);
};

But there appears to be no form element of req. Any ideas on what I'm doing wrong?

EDIT: POSTING MY req object

{ socket: 
   { bufferSize: 0,
     fd: 6,
     type: 'tcp4',
     allowHalfOpen: true,
     _readWatcher: 
      { socket: [Circular],
        callback: [Function: onReadable] },
     destroyed: false,
     readable: true,
     _writeQueue: [],
     _writeQueueEncoding: [],
     _writeQueueFD: [],
     _writeQueueCallbacks: [],
     _writeWatcher: 
      { socket: [Circular],
        callback: [Function: onWritable] },
     writable: true,
     _writeImpl: [Function],
     _readImpl: [Function],
     _shutdownImpl: [Function],
     remoteAddress: '127.0.0.1',
     remotePort: 59808,
     server: 
      { stack: [Object],
        connections: 6,
        allowHalfOpen: true,
        watcher: [Object],
        _events: [Object],
        httpAllowHalfOpen: false,
        cache: [Object],
        settings: [Object],
        redirects: {},
        isCallbacks: {},
        _locals: [Object],
        dynamicViewHelpers: [Object],
        errorHandlers: [],
        route: '/',
        routes: [Object],
        router: [Getter],
        __usedRouter: true,
        type: 'tcp4',
        fd: 9 },
     ondrain: [Function],
     _idleTimeout: 120000,
     _idleNext: 
      { bufferSize: 0,
        fd: 15,
        type: 'tcp4',
        allowHalfOpen: true,
        _readWatcher: [Object],
        destroyed: false,
        readable: true,
        _writeQueue: [],
        _writeQueueEncoding: [],
        _writeQueueFD: [],
        _writeQueueCallbacks: [],
        _writeWatcher: [Object],
        writable: true,
        _writeImpl: [Function],
        _readImpl: [Function],
        _shutdownImpl: [Function],
        remoteAddress: '127.0.0.1',
        remotePort: 59813,
        server: [Object],
        ondrain: [Function],
        _idleTimeout: 120000,
        _idleNext: [Object],
        _idlePrev: [Circular],
        _idleStart: Sun, 18 Dec 2011 18:45:05 GMT,
        _events: [Object],
        ondata: [Function],
        onend: [Function],
        _httpMessage: null },
     _idlePrev: 
      { repeat: 120,
        _idleNext: [Circular],
        _idlePrev: [Object],
        callback: [Function] },
     _idleStart: Sun, 18 Dec 2011 18:45:07 GMT,
     _events: 
      { timeout: [Function],
        error: [Function],
        close: [Function] },
     ondata: [Function],
     onend: [Function],
     _httpMessage: 
      { output: [],
        outputEncodings: [],
        writable: true,
        _last: false,
        chunkedEncoding: false,
        shouldKeepAlive: true,
        useChunkedEncodingByDefault: true,
        _hasBody: true,
        _trailer: '',
        finished: false,
        socket: [Circular],
        connection: [Circular],
        _events: [Object],
        _headers: [Object],
        _headerNames: [Object],
        app: [Object],
        req: [Circular],
        writeHead: [Function],
        end: [Function] } },
  connection: 
   { bufferSize: 0,
     fd: 6,
     type: 'tcp4',
     allowHalfOpen: true,
     _readWatcher: 
      { socket: [Circular],
        callback: [Function: onReadable] },
     destroyed: false,
     readable: true,
     _writeQueue: [],
     _writeQueueEncoding: [],
     _writeQueueFD: [],
     _writeQueueCallbacks: [],
     _writeWatcher: 
      { socket: [Circular],
        callback: [Function: onWritable] },
     writable: true,
     _writeImpl: [Function],
     _readImpl: [Function],
     _shutdownImpl: [Function],
     remoteAddress: '127.0.0.1',
     remotePort: 59808,
     server: 
      { stack: [Object],
        connections: 6,
        allowHalfOpen: true,
        watcher: [Object],
        _events: [Object],
        httpAllowHalfOpen: false,
        cache: [Object],
        settings: [Object],
        redirects: {},
        isCallbacks: {},
        _locals: [Object],
        dynamicViewHelpers: [Object],
        errorHandlers: [],
        route: '/',
        routes: [Object],
        router: [Getter],
        __usedRouter: true,
        type: 'tcp4',
        fd: 9 },
     ondrain: [Function],
     _idleTimeout: 120000,
     _idleNext: 
      { bufferSize: 0,
        fd: 15,
        type: 'tcp4',
        allowHalfOpen: true,
        _readWatcher: [Object],
        destroyed: false,
        readable: true,
        _writeQueue: [],
        _writeQueueEncoding: [],
        _writeQueueFD: [],
        _writeQueueCallbacks: [],
        _writeWatcher: [Object],
        writable: true,
        _writeImpl: [Function],
        _readImpl: [Function],
        _shutdownImpl: [Function],
        remoteAddress: '127.0.0.1',
        remotePort: 59813,
        server: [Object],
        ondrain: [Function],
        _idleTimeout: 120000,
        _idleNext: [Object],
        _idlePrev: [Circular],
        _idleStart: Sun, 18 Dec 2011 18:45:05 GMT,
        _events: [Object],
        ondata: [Function],
        onend: [Function],
        _httpMessage: null },
     _idlePrev: 
      { repeat: 120,
        _idleNext: [Circular],
        _idlePrev: [Object],
        callback: [Function] },
     _idleStart: Sun, 18 Dec 2011 18:45:07 GMT,
     _events: 
      { timeout: [Function],
        error: [Function],
        close: [Function] },
     ondata: [Function],
     onend: [Function],
     _httpMessage: 
      { output: [],
        outputEncodings: [],
        writable: true,
        _last: false,
        chunkedEncoding: false,
        shouldKeepAlive: true,
        useChunkedEncodingByDefault: true,
        _hasBody: true,
        _trailer: '',
        finished: false,
        socket: [Circular],
        connection: [Circular],
        _events: [Object],
        _headers: [Object],
        _headerNames: [Object],
        app: [Object],
        req: [Circular],
        writeHead: [Function],
        end: [Function] } },
  httpVersion: '1.1',
  complete: true,
  headers: 
   { host: 'localhost:3000',
     'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:8.0.1) Gecko/20100101 Firefox/8.0.1',
     accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
     'accept-language': 'en-us,en;q=0.5',
     'accept-encoding': 'gzip, deflate',
     'accept-charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
     connection: 'keep-alive',
     'x-requested-with': 'XMLHttpRequest',
     'x-file-name': 'lostCustomerList_1.csv',
     'content-type': 'application/octet-stream',
     referer: 'http://localhost:3000/client/wizard/customers',
     'content-length': '12278',
     cookie: 'wheel.cookie=BtKegWh26m5yNfrjnjN3h2sY.NgfTHkJ%2Fu3OenPY3euXHlU%2B818cUtqI2jyp%2FAQrcxI4',
     pragma: 'no-cache',
     'cache-control': 'no-cache' },
  trailers: {},
  readable: false,
  url: '/api/client/wizard/uploadCustomers?qqfile=lostCustomerList_1.csv',
  method: 'POST',
  statusCode: null,
  client: 
   { bufferSize: 0,
     fd: 6,
     type: 'tcp4',
     allowHalfOpen: true,
     _readWatcher: 
      { socket: [Circular],
        callback: [Function: onReadable] },
     destroyed: false,
     readable: true,
     _writeQueue: [],
     _writeQueueEncoding: [],
     _writeQueueFD: [],
     _writeQueueCallbacks: [],
     _writeWatcher: 
      { socket: [Circular],
        callback: [Function: onWritable] },
     writable: true,
     _writeImpl: [Function],
     _readImpl: [Function],
     _shutdownImpl: [Function],
     remoteAddress: '127.0.0.1',
     remotePort: 59808,
     server: 
      { stack: [Object],
        connections: 6,
        allowHalfOpen: true,
        watcher: [Object],
        _events: [Object],
        httpAllowHalfOpen: false,
        cache: [Object],
        settings: [Object],
        redirects: {},
        isCallbacks: {},
        _locals: [Object],
        dynamicViewHelpers: [Object],
        errorHandlers: [],
        route: '/',
        routes: [Object],
        router: [Getter],
        __usedRouter: true,
        type: 'tcp4',
        fd: 9 },
     ondrain: [Function],
     _idleTimeout: 120000,
     _idleNext: 
      { bufferSize: 0,
        fd: 15,
        type: 'tcp4',
        allowHalfOpen: true,
        _readWatcher: [Object],
        destroyed: false,
        readable: true,
        _writeQueue: [],
        _writeQueueEncoding: [],
        _writeQueueFD: [],
        _writeQueueCallbacks: [],
        _writeWatcher: [Object],
        writable: true,
        _writeImpl: [Function],
        _readImpl: [Function],
        _shutdownImpl: [Function],
        remoteAddress: '127.0.0.1',
        remotePort: 59813,
        server: [Object],
        ondrain: [Function],
        _idleTimeout: 120000,
        _idleNext: [Object],
        _idlePrev: [Circular],
        _idleStart: Sun, 18 Dec 2011 18:45:05 GMT,
        _events: [Object],
        ondata: [Function],
        onend: [Function],
        _httpMessage: null },
     _idlePrev: 
      { repeat: 120,
        _idleNext: [Circular],
        _idlePrev: [Object],
        callback: [Function] },
     _idleStart: Sun, 18 Dec 2011 18:45:07 GMT,
     _events: 
      { timeout: [Function],
        error: [Function],
        close: [Function] },
     ondata: [Function],
     onend: [Function],
     _httpMessage: 
      { output: [],
        outputEncodings: [],
        writable: true,
        _last: false,
        chunkedEncoding: false,
        shouldKeepAlive: true,
        useChunkedEncodingByDefault: true,
        _hasBody: true,
        _trailer: '',
        finished: false,
        socket: [Circular],
        connection: [Circular],
        _events: [Object],
        _headers: [Object],
        _headerNames: [Object],
        app: [Object],
        req: [Circular],
        writeHead: [Function],
        end: [Function] } },
  httpVersionMajor: 1,
  httpVersionMinor: 1,
  upgrade: false,
  originalUrl: '/api/client/wizard/uploadCustomers?qqfile=lostCustomerList_1.csv',
  query: { qqfile: 'lostCustomerList_1.csv' },
  app: 
   { stack: 
      [ [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object] ],
     connections: 6,
     allowHalfOpen: true,
     watcher: { host: [Circular], callback: [Function] },
     _events: 
      { request: [Function],
        connection: [Function: connectionListener],
        listening: [Function] },
     httpAllowHalfOpen: false,
     cache: { false: [Object] },
     settings: 
      { env: 'development',
        hints: true,
        views: '/Users/shamoon/Sites/rtem/views',
        'view engine': 'ejs' },
     redirects: {},
     isCallbacks: {},
     _locals: { settings: [Object], app: [Circular] },
     dynamicViewHelpers: { session: [Function], flash: [Function] },
     errorHandlers: [],
     route: '/',
     routes: 
      { app: [Circular],
        routes: [Object],
        params: {},
        _params: [],
        middleware: [Function] },
     router: [Getter],
     __usedRouter: true,
     type: 'tcp4',
     fd: 9 },
  res: 
   { output: [],
     outputEncodings: [],
     writable: true,
     _last: false,
     chunkedEncoding: false,
     shouldKeepAlive: true,
     useChunkedEncodingByDefault: true,
     _hasBody: true,
     _trailer: '',
     finished: false,
     socket: 
      { bufferSize: 0,
        fd: 6,
        type: 'tcp4',
        allowHalfOpen: true,
        _readWatcher: [Object],
        destroyed: false,
        readable: true,
        _writeQueue: [],
        _writeQueueEncoding: [],
        _writeQueueFD: [],
        _writeQueueCallbacks: [],
        _writeWatcher: [Object],
        writable: true,
        _writeImpl: [Function],
        _readImpl: [Function],
        _shutdownImpl: [Function],
        remoteAddress: '127.0.0.1',
        remotePort: 59808,
        server: [Object],
        ondrain: [Function],
        _idleTimeout: 120000,
        _idleNext: [Object],
        _idlePrev: [Object],
        _idleStart: Sun, 18 Dec 2011 18:45:07 GMT,
        _events: [Object],
        ondata: [Function],
        onend: [Function],
        _httpMessage: [Circular] },
     connection: 
      { bufferSize: 0,
        fd: 6,
        type: 'tcp4',
        allowHalfOpen: true,
        _readWatcher: [Object],
        destroyed: false,
        readable: true,
        _writeQueue: [],
        _writeQueueEncoding: [],
        _writeQueueFD: [],
        _writeQueueCallbacks: [],
        _writeWatcher: [Object],
        writable: true,
        _writeImpl: [Function],
        _readImpl: [Function],
        _shutdownImpl: [Function],
        remoteAddress: '127.0.0.1',
        remotePort: 59808,
        server: [Object],
        ondrain: [Function],
        _idleTimeout: 120000,
        _idleNext: [Object],
        _idlePrev: [Object],
        _idleStart: Sun, 18 Dec 2011 18:45:07 GMT,
        _events: [Object],
        ondata: [Function],
        onend: [Function],
        _httpMessage: [Circular] },
     _events: { finish: [Function] },
     _headers: { 'x-powered-by': 'Express' },
     _headerNames: { 'x-powered-by': 'X-Powered-By' },
     app: 
      { stack: [Object],
        connections: 6,
        allowHalfOpen: true,
        watcher: [Object],
        _events: [Object],
        httpAllowHalfOpen: false,
        cache: [Object],
        settings: [Object],
        redirects: {},
        isCallbacks: {},
        _locals: [Object],
        dynamicViewHelpers: [Object],
        errorHandlers: [],
        route: '/',
        routes: [Object],
        router: [Getter],
        __usedRouter: true,
        type: 'tcp4',
        fd: 9 },
     req: [Circular],
     writeHead: [Function],
     end: [Function] },
  next: [Function: next],
  body: {},
  originalMethod: 'POST',
  cookies: { 'wheel.cookie': 'BtKegWh26m5yNfrjnjN3h2sY.NgfTHkJ/u3OenPY3euXHlU+818cUtqI2jyp/AQrcxI4' },
  sessionStore: 
   { db: 
      { databaseName: 'rtem',
        serverConfig: [Object],
        options: {},
        native_parser: undefined,
        bson_serializer: [Object],
        bson_deserializer: [Object],
        state: 'connected',
        pkFactory: [Object],
        forceServerObjectId: false,
        operationTimeout: 1000,
        strict: false,
        notReplied: {},
        isInitializing: true,
        auths: [],
        logger: [Object],
        slaveOk: false,
        tag: 1324233903416,
        _mongodbHandlers: [Object],
        eventHandlers: [Object],
        serializeFunctions: false,
        raw: false,
        retryMiliSeconds: 5000,
        numberOfRetries: 5,
        reaperInterval: 1000,
        reaperTimeout: 30000,
        reaperIntervalId: [Object] },
     db_collection_name: 'sessions',
     _get_collection: [Function],
     hash: [Function],
     generate: [Function],
     collection: 
      { db: [Object],
        collectionName: 'sessions',
        opts: {},
        slaveOk: false,
        serializeFunctions: false,
        raw: false,
        pkFactory: [Object],
        hint: [Getter/Setter] } },
  sessionID: 'BtKegWh26m5yNfrjnjN3h2sY.NgfTHkJ/u3OenPY3euXHlU+818cUtqI2jyp/AQrcxI4',
  _events: { data: [Function], end: [Function] },
  session: 
   { lastAccess: 1324233907666,
     cookie: 
      { path: '/',
        httpOnly: true,
        _expires: Sun, 18 Dec 2011 22:45:05 GMT,
        originalMaxAge: 14399999 },
     flash: {},
     authenticator: 
      { _id: '4ee4e47e66634f503b11ecad',
        email: 'test@test.com',
        name: 'test',
        password: 'test',
        addedOn: '2011-12-18T16:55:40.003Z',
        client: [Object],
        status: 'client' } },
  _route_index: 6,
  route: 
   { path: '/api/client/wizard/uploadCustomers',
     method: 'post',
     callbacks: [ [Function] ],
     keys: [],
     regexp: /^\/api\/client\/wizard\/uploadCustomers\/?$/i,
     params: [] },
  params: [] }

Solution

  • This module is now deprecated and will eventually be removed, Connect >= 1.8.0 bodyParser() supports multipart/form-data, populating req.body much like application/json. An alternative to the core's bodyParser() is parted.

    connect-form is deprecated. Use the body parser, it understands multipart/form-data.

    Specifically, bodyParser will write to req.files. Go read the bodyParser example