Форма не определена при использовании модуля connect-form - PullRequest
0 голосов
/ 21 октября 2011

У меня есть экспресс-приложение, в котором я хочу использовать модуль connect-form для обработки некоторых форм загрузки файлов. Я следовал примерам в экспресс-репозитории GitHub и в форме подключения, но когда я звоню req.form.complete(function(){}), я получаю сообщение об ошибке 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: [] }

Ответы [ 2 ]

0 голосов
/ 22 октября 2011

Я не уверен, почему connect-form не работает, но я обнаружил, что она написана поверх модуля 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 голосов
/ 21 октября 2011

Предположим, что форма не отправлена ​​со стороны браузера, см. Пример, приведенный в 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 !!

...