Created
October 17, 2012 19:56
-
-
Save asnowfix/3907749 to your computer and use it in GitHub Desktop.
test case showing difference between node-formidable multipart/form-data streams and fs.File streams
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var fs = require("fs"); | |
var path = require("path"); | |
var express = require("express"); | |
var util = require("util"); | |
var querystring = require("querystring"); | |
var temp = require("temp"); | |
var zipstream = require('zipstream'); | |
var formidable = require('formidable'); | |
function Zipper(config, next) { | |
function HttpError(msg, statusCode) { | |
Error.captureStackTrace(this, this); | |
this.statusCode = statusCode || 500; // Internal-Server-Error | |
this.message = msg || 'Error'; | |
} | |
util.inherits(HttpError, Error); | |
HttpError.prototype.name = "HTTP Error"; | |
// (simple) parameters checking | |
config.pathname = config.pathname || '/zip'; | |
var app = express.createServer(); | |
app.use(express.logger('dev')); | |
// Error handler | |
app.error(function(err, req, res, next){ | |
res.status(err.statusCode || 500).send(err.toString()); | |
}); | |
// Create archive | |
app.post('/zip', function(req, res, next) { | |
var form, zip, tasks, zipping = false; | |
var files = [], fields = []; | |
try { | |
if (!req.is('multipart/form-data')) { | |
next(new HttpError("Not a multipart request", 415 /*Unsupported Media Type*/)); | |
return; | |
} | |
tasks = []; | |
res.contentType('application/zip'); | |
zip = zipstream.createZip({level: 1}); | |
zip.pipe(res); | |
form = new formidable.IncomingForm(); | |
// We use an intermediate temporary directory, | |
// because the following issue prevents piping | |
// directly node-formidable input-streams into | |
// a node-zipstream output-stream (archive). | |
// <https://github.com/felixge/node-formidable/issues/182>, | |
if (config.useFiles) { | |
console.log("using file-based zipping"); | |
form.uploadDir = temp.path({prefix: 'zipper.'}) + '.d'; | |
fs.mkdirSync(form.uploadDir); | |
form.on('file', function(field, file) { | |
files.push(file); | |
tasks.push(function() { | |
zipping = true; | |
zip.addFile(new fs.createReadStream(file.path), {name: file.name}, function() { | |
console.log("added", file.name); | |
zipping = false; | |
_nextTask(); | |
}); | |
}); | |
}); | |
form.on('field', function(field, value) { | |
console.log(field, value); | |
fields.push([field, value]); | |
}); | |
} else { | |
console.log("using part-based zipping"); | |
form.onPart = function(part) { | |
if (!part.filename) { | |
// let formidable handle all non-file parts | |
form.handlePart(part); | |
} else { | |
tasks.push(function() { | |
zipping = true; | |
zip.addFile(part, {name: part.filename}, function() { | |
console.log("added", part.filename); | |
zipping = false; | |
_nextTask(); | |
}); | |
}); | |
_nextTask(); | |
} | |
}; | |
} | |
form.on('end', function() { | |
tasks.push(function() { | |
zip.finalize(function(written) { | |
res.status(201 /*Created*/).end(); | |
if (config.useFiles) { | |
_clean(); | |
} | |
}); | |
}); | |
_nextTask(); | |
}); | |
function _nextTask() { | |
if (!zipping) { | |
var task = tasks.shift(); | |
task && task(); | |
} | |
} | |
form.parse(req, function(err) { | |
if (err) { | |
next(err); | |
} | |
}); | |
function _clean(next) { | |
var file, count = files.length; | |
function _rmdir() { | |
(count === 0) && fs.rmdir(form.uploadDir, next); | |
} | |
_rmdir(); | |
while ((file = files.shift())) { | |
fs.unlink(file.path, function(err) { | |
if (err) { | |
next(err); | |
return; | |
} | |
count--; | |
_rmdir(); | |
}); | |
} | |
} | |
} catch(e) { | |
console.error(e.stack); | |
next(new HttpError(e.msg)); | |
} | |
}); | |
app.listen(9019, "127.0.0.1", null /*backlog*/, function() { | |
return next(); | |
}); | |
this.quit = function() { | |
app.close(); | |
}; | |
} | |
if (path.basename(process.argv[1]) === "formidable-issue182.js") { | |
var zipper = new Zipper({ | |
useFiles: !!process.argv[2] | |
}, function(err){ | |
if (err) { | |
process.exit(err); | |
} | |
if (process.send) { | |
process.send({ok: true}); | |
} | |
}); | |
} else { | |
module.exports = Zipper; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment