2011年11月27日 星期日

NodeJS + Express 實作檔案上傳

Standard
Express Web Framework』是基於『Connect Middleware Framework』所開發,大部份的常見功能,藉由 Connect 本身支援或 Connect 的第三方(Third-party)模組,就可以實作出來。如果要實作檔案上傳的功能,可以使用第三方模組『connect-form』來達成。

直接透過 npm 安裝需要的模組:
npm install connect-form

在 app.js 中實作:
var express = require('express');
var form = require('connect-form');
var app = module.exports = express.createServer();

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(form({
    keepExtensions: true,
    uploadDir: __dirname + '/uploads'
  }));
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.get('/', function(req, res) {
  res.send('<form method="post" enctype="multipart/form-data">'
    + '<p>Image: <input type="file" name="image" /></p>'
    + '<p><input type="submit" value="Upload" /></p>'
    + '</form>');
});

app.post('/', function(req, res, next) {
  req.form.complete(function(err, fields, files){
    if (err) {
      next(err);
    } else {
      console.log('\nuploaded %s to %s'
        ,  files.image.filename
        , files.image.path);
      res.redirect('back');
    }
  });

  req.form.on('progress', function(bytesReceived, bytesExpected){
    var percent = (bytesReceived / bytesExpected * 100) | 0;
    process.stdout.write('Uploading: %' + percent + '\r');
  });
});

app.listen(3000);

後記

本文的範例與 express 所提供的是一樣的,只是在 app.configure() 裡多了幾行 app.use()。其實目的只是希望告訴讀者,務必要在 app.router 之前引入 connect-form。原因是在 Express Web Framework 設計上,每次處理 Request 時,會依照 app.use() 所引入的順序去使用模組。

由於原生的 app.router 並不處理上傳檔案的特殊需求,我們一定要在 Request 經過 app.router 導引並進入 app.post() 所定義的 handler 之前,讓 connect-form 先行遇處理和檢查 Request 是否為上傳檔案,進而擴充功能甚至進一步分析處理。