2011-10-21 74 views
0

我有一個快速應用程序,我想使用連接表單模塊來處理某些文件上載表單。我遵循快速GitHub回購和連接形式中的示例,但是當我撥打req.form.complete(function(){})時出現I Cannot call method 'complete' of undefined錯誤。下面是我的代碼:使用連接表單模塊時表單是未定義的

var express = require('express'), 
    knox = require('knox'), 
    form = require('connect-form')/*, 
    controller = require('controller').Controller*/; 
var app = module.exports = express.createServer(); 

// Configuration 
var port = process.env.PORT || 3000; 

app.configure(function(){ 
    app.set('views', __dirname + '/views'); 
    app.set('view engine', 'jade'); 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(app.router); 
    app.use(express.static(__dirname + '/public')); 

    form({ keepExtensions: true }); 
}); 

app.configure('development', function(){ 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

app.configure('production', function(){ 
    app.use(express.errorHandler()); 
}); 

// Routes 
app.get('/', function(req, res){ 
    res.render('index', { 
     title: 'Express' 
    }); 
}); 

app.get('/manage/new', function(req, res){ 
    res.render('manage/new', { 
     title: 'Create a new widget' 
    }); 
}); 

app.post('/manage/new', function(req, res, next){ 
    if(!req.form){ 
     res.send('Form not submitted.', {'Content-Type': 'text/plain'}, 500); 
     console.log(req); 
    } 
    else{ 
     req.form.complete(function(err, fields, files){ 
      if(err) next(err); 
      else { 
       console.log('\nuploaded %s to %s', files.download.filename, files.download.path); 
       res.redirect('back'); 
      } 
     }); 
     console.log(req.form); 
    } 
}); 

app.listen(port); 
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env); 

我的玉模板:

h1= title 

#wrapper 
    #main 
     form(method="post", enctype="multipart/form-data", name="create-widget") 
      .errors 

      fieldset 
       legend Band/Album Information 
       p 
        label.tooltip(for="txtTitle", data-tooltip="Band name or title to use on widget.") Band Name 
        br 
        input#txtTitle.input_full(name="title", placeholder="The Beatles") 
       p 
        label.tooltip(for="txtAlbum", data-tooltip="Album title shown on widget") Album 
        br 
        input#txtAlbum.input_full(name="album", placeholder="Magical Mystery Tour") 
       p 
        label.tooltip(for="fileDownload", data-tooltip="File to be downloaded after submitting form on Widget") Download 
        br 
        input#fileDownload.input_full(name="download", type="file") 
      #actions 
       input(type="submit", value="Generate Widget") 

有什麼我做錯了我的代碼?另外,當上傳下載字段時,我確實想直接將文件上傳到S3存儲桶。我是否有權訪問正在上傳的流,以便使上傳速度更快?

編輯

這裏是REQ對象的內容,當我提交表單:

{ 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: 51588, 
    server: 
     { stack: [Object], 
     connections: 1, 
     allowHalfOpen: true, 
     watcher: [Object], 
     _events: [Object], 
     httpAllowHalfOpen: false, 
     cache: {}, 
     settings: [Object], 
     redirects: {}, 
     isCallbacks: {}, 
     _locals: [Object], 
     dynamicViewHelpers: {}, 
     errorHandlers: [], 
     route: '/', 
     routes: [Object], 
     router: [Getter], 
     __usedRouter: true, 
     type: 'tcp4', 
     fd: 7 }, 
    ondrain: [Function], 
    _idleTimeout: 120000, 
    _idleNext: 
     { repeat: 120, 
     _idleNext: [Circular], 
     _idlePrev: [Circular], 
     callback: [Function] }, 
    _idlePrev: 
     { repeat: 120, 
     _idleNext: [Circular], 
     _idlePrev: [Circular], 
     callback: [Function] }, 
    _idleStart: Fri, 21 Oct 2011 16:08:07 GMT, 
    _events: 
     { timeout: [Function], 
     error: [Function], 
     close: [Function] }, 
    ondata: [Function], 
    onend: [Function], 
    _httpMessage: null }, 
    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: 51588, 
    server: 
     { stack: [Object], 
     connections: 1, 
     allowHalfOpen: true, 
     watcher: [Object], 
     _events: [Object], 
     httpAllowHalfOpen: false, 
     cache: {}, 
     settings: [Object], 
     redirects: {}, 
     isCallbacks: {}, 
     _locals: [Object], 
     dynamicViewHelpers: {}, 
     errorHandlers: [], 
     route: '/', 
     routes: [Object], 
     router: [Getter], 
     __usedRouter: true, 
     type: 'tcp4', 
     fd: 7 }, 
    ondrain: [Function], 
    _idleTimeout: 120000, 
    _idleNext: 
     { repeat: 120, 
     _idleNext: [Circular], 
     _idlePrev: [Circular], 
     callback: [Function] }, 
    _idlePrev: 
     { repeat: 120, 
     _idleNext: [Circular], 
     _idlePrev: [Circular], 
     callback: [Function] }, 
    _idleStart: Fri, 21 Oct 2011 16:08:07 GMT, 
    _events: 
     { timeout: [Function], 
     error: [Function], 
     close: [Function] }, 
    ondata: [Function], 
    onend: [Function], 
    _httpMessage: null }, 
    httpVersion: '1.1', 
    complete: false, 
    headers: 
    { host: '127.0.0.1:5000', 
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:6.0) Gecko/20100101 Firefox/6.0', 
    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', 
    referer: 'http://127.0.0.1:5000/manage/new', 
    'content-type': 'multipart/form-data; boundary=---------------------------20072377098235644401115438165', 
    'content-length': '247075' }, 
    trailers: {}, 
    readable: true, 
    url: '/manage/new', 
    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: 51588, 
    server: 
     { stack: [Object], 
     connections: 1, 
     allowHalfOpen: true, 
     watcher: [Object], 
     _events: [Object], 
     httpAllowHalfOpen: false, 
     cache: {}, 
     settings: [Object], 
     redirects: {}, 
     isCallbacks: {}, 
     _locals: [Object], 
     dynamicViewHelpers: {}, 
     errorHandlers: [], 
     route: '/', 
     routes: [Object], 
     router: [Getter], 
     __usedRouter: true, 
     type: 'tcp4', 
     fd: 7 }, 
    ondrain: [Function], 
    _idleTimeout: 120000, 
    _idleNext: 
     { repeat: 120, 
     _idleNext: [Circular], 
     _idlePrev: [Circular], 
     callback: [Function] }, 
    _idlePrev: 
     { repeat: 120, 
     _idleNext: [Circular], 
     _idlePrev: [Circular], 
     callback: [Function] }, 
    _idleStart: Fri, 21 Oct 2011 16:08:07 GMT, 
    _events: 
     { timeout: [Function], 
     error: [Function], 
     close: [Function] }, 
    ondata: [Function], 
    onend: [Function], 
    _httpMessage: null }, 
    httpVersionMajor: 1, 
    httpVersionMinor: 1, 
    upgrade: false, 
    originalUrl: '/manage/new', 
    query: {}, 
    app: 
    { stack: 
     [ [Object], 
     [Object], 
     [Object], 
     [Object], 
     [Object], 
     [Object] ], 
    connections: 1, 
    allowHalfOpen: true, 
    watcher: { host: [Circular], callback: [Function] }, 
    _events: 
     { request: [Function], 
     connection: [Function: connectionListener], 
     listening: [Function] }, 
    httpAllowHalfOpen: false, 
    cache: {}, 
    settings: 
     { env: 'development', 
     hints: true, 
     views: '/Users/davejlong/Workspace/Node/Widget/views', 
     'view engine': 'jade' }, 
    redirects: {}, 
    isCallbacks: {}, 
    _locals: { settings: [Object], app: [Circular] }, 
    dynamicViewHelpers: {}, 
    errorHandlers: [], 
    route: '/', 
    routes: 
     { app: [Circular], 
     routes: [Object], 
     params: {}, 
     _params: [], 
     middleware: [Function] }, 
    router: [Getter], 
    __usedRouter: true, 
    type: 'tcp4', 
    fd: 7 }, 
    res: 
    { output: [], 
    outputEncodings: [], 
    writable: true, 
    _last: false, 
    chunkedEncoding: false, 
    shouldKeepAlive: true, 
    useChunkedEncodingByDefault: true, 
    _hasBody: true, 
    _trailer: '', 
    finished: true, 
    socket: null, 
    connection: null, 
    _events: { finish: [Function] }, 
    _headers: 
     { 'x-powered-by': 'Express', 
     'content-type': 'text/plain; charset=utf-8', 
     'content-length': 19 }, 
    _headerNames: 
     { 'x-powered-by': 'X-Powered-By', 
     'content-type': 'Content-Type', 
     'content-length': 'Content-Length' }, 
    app: 
     { stack: [Object], 
     connections: 1, 
     allowHalfOpen: true, 
     watcher: [Object], 
     _events: [Object], 
     httpAllowHalfOpen: false, 
     cache: {}, 
     settings: [Object], 
     redirects: {}, 
     isCallbacks: {}, 
     _locals: [Object], 
     dynamicViewHelpers: {}, 
     errorHandlers: [], 
     route: '/', 
     routes: [Object], 
     router: [Getter], 
     __usedRouter: true, 
     type: 'tcp4', 
     fd: 7 }, 
    req: [Circular], 
    charset: 'utf-8', 
    statusCode: 500, 
    _header: 'HTTP/1.1 500 Internal Server Error\r\nX-Powered-By: Express\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: 19\r\nConnection: keep-alive\r\n\r\n', 
    _headerSent: true }, 
    next: [Function: next], 
    originalMethod: 'POST', 
    _route_index: 0, 
    route: 
    { path: '/manage/new', 
    method: 'post', 
    callbacks: [ [Function] ], 
    keys: [], 
    regexp: /^\/manage\/new\/?$/i, 
    params: [] }, 
    params: [] } 

回答

0

我不確定爲什麼連接表單不起作用,但我發現它是寫在Formidable模塊的頂部,所以我拿了它,只是用在我的路由器,而不是它正確地拿起形式:

var sys = require('sys'), 
    express = require('express'), 
    knox = require('knox'), 
    formidable = require('formidable'), 
    controller = require('./controller').Controller; 
var app = module.exports = express.createServer(); 

/* ================================================================ */ 
/*       Configuration       */ 
/* ================================================================ */ 
var port = process.env.PORT || 3000; 
var hostName = 'http://download.comeandlive.com'; 
controller.setup(hostName, 80); 

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

app.configure('development', function(){ 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

app.configure('production', function(){ 
    app.use(express.errorHandler()); 
}); 

/* ================================================================ */ 
/*         Routes       */ 
/* ================================================================ */ 
app.get('/', function(req, res){ 
    res.redirect('http://comeandlive.com', 301); 
}); 

/* ================================ */ 
/*  Administration Routes  */ 
/* ================================ */ 
app.get('/manage', function(req, res){ 
    res.render('manage/index', { 
     title: 'Widget Administration' 
    }); 
}) 
app.get('/manage/new', function(req, res){ 
    res.render('manage/new', { 
     title: 'Create a new widget' 
    }); 
}); 

app.post('/manage/new', function(req, res, next){ 
    var form = new formidable.IncomingForm(); 
    form.parse(req, function(err, fields, files){ 
     res.header('Content-Type', 'text/plain'); 
     res.send('Received upload:\n\n' + sys.inspect({fields:fields, files:files})); 
    }); 
}); 


app.listen(port); 
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env); 
0

競猜形式不從布勞爾方提交,請參閱提供http://visionmedia.github.com/connect-form/

例子
var form = require('connect-form'); 
var server = connect.createServer(
     form({ keepExtensions: true }), 
     function(req, res, next){ 
      // Form was submitted 
     if (req.form) { 
      // Do something when parsing is finished 
      // and respond, or respond immediately 
      // and work with the files. 
      req.form.onComplete = function(err, fields, files){ 
       res.writeHead(200, {}); 
       if (err) res.write(JSON.stringify(err.message)); 
       res.write(JSON.stringify(fields)); 
       res.write(JSON.stringify(files)); 
       res.end(); 
      }; 
     // Regular request, pass to next middleware 
     } else { 
      next(); 
     } 
    } 
); 

「if(req.form)」在示例中確保表單確實已提交!您應該這樣做,以及您可能無法控制發佈到您的API的內容!

+0

req.form從來沒有存在過。即使當我知道我已經提交了一個表單,它也會回到未定義狀態。 –

+0

我用新的app.js更新了我的問題,並添加了req對象的內容。 –