Skip to content

Instantly share code, notes, and snippets.

@josevalim
Created January 4, 2011 08:29
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save josevalim/764536 to your computer and use it in GitHub Desktop.
Save josevalim/764536 to your computer and use it in GitHub Desktop.
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`):
//
// https://github.com/assaf/zombie/blob/master/src/zombie/history.coffee#L93
//
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){
console.log(browser.html());
});
});
require "rubygems"
require "sinatra"
helpers do
include Rack::Utils
alias_method :h, :escape_html
end
get "/upload" do
<<-HTML
<html>
<head>
<title>Upload</title>
</head>
<body>
<form enctype="multipart/form-data" action="/upload" method="post">
<label>File<input type="file" name="form[file]"></label>
<input type="submit" value="Upload">
</form>
</body>
</html>
HTML
end
post "/upload" do
h(params.inspect).tap do
puts request.env.inspect
puts request.env["rack.request.form_input"].read.inspect
end
end
@phstc
Copy link

phstc commented Jun 14, 2012

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

uploader/node_modules/zombie/lib/zombie/forms.js:111
  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 Object.click (/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 Browser.fire (/Users/pablo/workspace/super/uploader/node_modules/zombie/lib/zombie/browser.js:201:10)

app.js

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

app.listen(4567);

function handler (req, res) {
    if (req.url.match(/^\/upload.+/) && req.method.toLowerCase() == 'post') {
        upload(req, res);
        return;
    }
    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 + '/' + file.name);
    });

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

function index(req, res){
    fs.readFile(__dirname + '/public/index.html', 'utf8', function(err, html){
        res.end(html);
    });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment