Reputation: 8004
I am having troubles getting file uploads to work with NodeJS. I am using Dropzone.JS to create a form that sends a POST request to /file-upload here:
<form action="/file-upload" class="dropzone dragndrop" id="my-awesome-dropzone"></form>
Then I have a route in app.js:
app.post('/file-upload', routes.upload);
Then my handler:
exports.upload = function(req, res){
console.log(req.files);
res.send("OK");
}
However, the upload function here is never called. The server crashes with this error first:
events.js:69
throw arguments[1]; // Unhandled 'error' event
^
Error: Invalid data
at WriteStream._write (fs.js:1616:31)
at onwrite (_stream_writable.js:265:14)
at WritableState.onwrite (_stream_writable.js:94:5)
at fs.js:1628:5
at Object.wrapper [as oncomplete] (fs.js:475:5)
at process._makeCallback (node.js:321:24)
So I am not sure what I should do because it appears that this is not my fault. I followed other tutorials and saw nothing wrong. Also, when I inspect my Network under chrome dev tools, it shows:
Request URL:http://localhost:3000/file-upload
**Request Headers**
Accept:application/json
Cache-Control:no-cache
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryMmLSkbfQskfIcjfE
Origin:http://localhost:3000
Pragma:no-cache
Referer:http://localhost:3000/
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
X-File-Name:Screenshot from 2013-03-20 12:23:42.png
X-Requested-With:XMLHttpRequest
**Request Payload**
------WebKitFormBoundaryMmLSkbfQskfIcjfE
Content-Disposition: form-data; name="file"; filename="Screenshot from 2013-03-20 12:23:42.png"
Content-Type: image/png
------WebKitFormBoundaryMmLSkbfQskfIcjfE--
Upvotes: 17
Views: 57526
Reputation: 1178
Most recent up-to-date version:
const express = require("express");
const app = express();
const bodyParser = require('body-parser');
const multer = require('multer');
// serve your HTML form
app.use(express.static('public'));
// parse application/json
app.use(bodyParser.json());
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// parse multipart/form-data
app.use(multer({dest:__dirname+'/uploads/'}).any());
app.post("/upload", function (request, response) {
// request.files will contain the uploaded file(s),
// keyed by the input name (in this case, "file")
// show the uploaded files
console.log("file name", request.files);
response.end("upload complete");
});
app.listen(3000, "0.0.0.0");
npm install express --save
npm install body-parser --save
npm install multer --save
Upvotes: 0
Reputation: 798
Try use busboy-body-parser to retrieve the request body parameters and the files.
start.js
var bodyParser = require('body-parser');
var busboyBodyParser = require('busboy-body-parser');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
extended: true
}));
// parse application/json
app.use(bodyParser.json());
//parse multipart/form-data
app.use(busboyBodyParser());
controllers/someController.js
someAction: function(req,res){
if(req.method == "POST"){
res.end(JSON.stringify(req.body)+JSON.stringify(req.files));
}
}
//{"text":"testx"}{"anexo":{"data":{"type":"Buffer","data":.... }}}
//req.body = {"text":"testx"}
//req.files = {"anexo":{"data":{"type":"Buffer","data":.... }}}
views/someController/someAction.html
<form method="post" id="multipart" enctype="multipart/form-data">
<input type="text" id="text1" name="text" value="testx" />
<input type="file" id="anexo" name="anexo" />
<input type="submit" value="Enviar" />
</form>
To create a file uploaded, you need work if the stream, for example:
/* file props
{
"data":{"type":"Buffer","data":.... },
"fieldname":"anexo",
"originalname":"images (1).jpg",
"encoding":"7bit",
"mimetype":"image/jpeg",
"destination":"c:\\live\\sources\\uploads\\",
"filename":"eventclock_images(1)_1443706175833.jpg",
"path":"c:\\live\\sources\\uploads\\eventclock_images(1)_1443706175833.jpg",
"size":9986
}
*/
var fileStream = fs.createWriteStream(file.path);
fileStream.write(file.data);
fileStream.end();
fileStream.on('error', function (err) {
//console.log("error",err);
});
fileStream.on('finish', function (res) {
//console.log("finish",res);
});
Upvotes: 2
Reputation: 1334
@user568109 and @nick-fishman are correct; you should use the bodyParser middleware for this.
Please see the sample code for a basic file upload form below. (Note: you will need to create an "uploads" directory to store the files.)
file-upload.js:
var express = require("express"),
app = express();
// tell express to use the bodyParser middleware
// and set upload directory
app.use(express.bodyParser({ keepExtensions: true, uploadDir: "uploads" }));
app.engine('jade', require('jade').__express);
app.post("/upload", function (request, response) {
// request.files will contain the uploaded file(s),
// keyed by the input name (in this case, "file")
// show the uploaded file name
console.log("file name", request.files.file.name);
console.log("file path", request.files.file.path);
response.end("upload complete");
});
// render file upload form
app.get("/", function (request, response) {
response.render("upload_form.jade");
});
app.listen(3000);
views/upload_form.jade:
doctype 5
html
head
title Upload Form
body
h1 Upload File
form(method="POST", action="/upload", enctype="multipart/form-data")
input(type="file", name="file")
input(type="submit")
Upvotes: 17
Reputation: 654
@user568109 is correct: you need ExpressJS and bodyParser enabled. Do you have a line similar to the following in your configuration?
app.use(express.bodyParser({ keepExtensions: true, uploadDir: '/my/files' }));
Upvotes: 2