Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Improve file uploads with Zombie
// Improvements to file uploads with Zombie.
// Just start the Sinatra server below and run this file with node.
// Depending on the server used with Sinatra, it will fail upfront or forward
// a bad request to the app. The source code in zombie is in the link below
// (you will need Zombie from git, you can check it out and use `npm link`):
var zombie = require("zombie");
var browser = new zombie.Browser;
browser.visit("http://localhost:4567/upload", function (err) {
browser.attach("File", __filename)
browser.pressButton("Upload", function(err){
require "rubygems"
require "sinatra"
helpers do
include Rack::Utils
alias_method :h, :escape_html
get "/upload" do
<form enctype="multipart/form-data" action="/upload" method="post">
<label>File<input type="file" name="form[file]"></label>
<input type="submit" value="Upload">
post "/upload" do
h(params.inspect).tap do
puts request.env.inspect
puts request.env["rack.request.form_input"].read.inspect

phstc commented Jun 14, 2012

Hey! I got an error testing this client.js with a node.js server.

  return this.ownerDocument.parentWindow.browser.dispatchEvent(this, event);
TypeError: Cannot call method 'dispatchEvent' of undefined
    at Object._dispatchSubmitEvent (/Users/pablo/workspace/super/uploader/node_modules/zombie/lib/zombie/forms.js:111:50)
    at (/Users/pablo/workspace/super/uploader/node_modules/zombie/lib/zombie/forms.js:136:23)
    at Object.dispatchEvent (/Users/pablo/workspace/super/uploader/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:480:47)
    at /Users/pablo/workspace/super/uploader/node_modules/zombie/lib/zombie/eventloop.js:135:40
    at Object._evaluate (/Users/pablo/workspace/super/uploader/node_modules/zombie/lib/zombie/windows.js:271:23)
    at /Users/pablo/workspace/super/uploader/node_modules/zombie/lib/zombie/eventloop.js:134:14
    at EventLoop.perform (/Users/pablo/workspace/super/uploader/node_modules/zombie/lib/zombie/eventloop.js:120:5)
    at EventLoop.dispatch (/Users/pablo/workspace/super/uploader/node_modules/zombie/lib/zombie/eventloop.js:131:10)
    at Browser.dispatchEvent (/Users/pablo/workspace/super/uploader/node_modules/zombie/lib/zombie/browser.js:206:28)
    at (/Users/pablo/workspace/super/uploader/node_modules/zombie/lib/zombie/browser.js:201:10)


var app = require('http').createServer(handler)
    , formidable = require('formidable')
    , fs = require('fs');


function handler (req, res) {
    if (req.url.match(/^\/upload.+/) && req.method.toLowerCase() == 'post') {
        upload(req, res);
    index(req, res);

function upload(req, res){
    var form = new formidable.IncomingForm();

    form.uploadDir = __dirname + '/public/uploaded_files';

    form.parse(req, function(err, fields, files) {
        res.writeHead(200, {'Content-type': 'text/plain'});
        res.end('upload received');

    form.on('file', function(field, file) {
        fs.rename(file.path, form.uploadDir + '/' +;

    form.addListener('progress' , function(bytesReceived, bytesExpected){
        var percentage = parseInt((bytesReceived * 100) / bytesExpected, 10);

function index(req, res){
    fs.readFile(__dirname + '/public/index.html', 'utf8', function(err, html){
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment