Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload multiple files with XMLHttpRequest to Express.js 3.5 Server

I'm trying to build a file uploader with the native FileAPI in JavaScript and I want to upload the files via XMLHttpRequest (without jQuery) to a Node.js server, which uses Express.js.

The file reading part works fine and when I upload the file without the XMLHttpRequest it works perfectly (the files are in req.files in Express.js).

The problem is the upload via AJAX: req.files is always empty.

Heres some code:

The form:

<form action="http://localhost:3000/upload" method="POST" enctype="multipart/form-data" name="form">
  <input type="file" name="uploads" id="files" multiple="multiple">
  <input type="submit" name="submit" value="submit">
</form>

The upload part in the frontend (in files[0].data is a file - not an array or something):

function uploadFiles(files) {
    var xhr = new XMLHttpRequest();
    xhr.submittedData = files; // Array of objects with files included. But it neither works with an array of files nor just one file
    xhr.onload = successfullyUploaded;
    xhr.open("POST", "http://localhost:3000/upload", true);
    xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
    xhr.send();
}

The backend where the problem occurs:

exports.receiveUpload = function(req, res){
    console.log(req.files); // empty
    var files = req.files.uploads; // always empty with AJAX upload. with normal upload it's fine
    console.log(req.xhr); // true
    // ...
}

And here's some Express.js config (I already had the same error without AJAX - in the comments in the code you can see the lines and the Stack Overflow post that solved it for the upload without AJAX):

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());

// this 3 lines have to be before app.use(app.router)
// https://stackoverflow.com/questions/21877098/upload-file-using-express-failed-cannot-read-property-of-undefined
app.use(express.multipart());
app.use(express.bodyParser({ keepExtensions: true, uploadDir: path.join(__dirname, 'public', 'uploads') }));
app.use(express.methodOverride());


app.use(app.router);
app.use(require('less-middleware')(path.join(__dirname, '/public')));
app.use(express.static(path.join(__dirname, 'public')));

Thanks in advance!

Regards,

C.

like image 824
lehnerchristian Avatar asked Apr 12 '14 20:04

lehnerchristian


People also ask

How do I upload a file using XMLHttpRequest?

Create the form object for submission The formData will contain the file object which can be easily appended. Then an AJAX request can be created by using XMLHttpRequest() method. This would be a POST request to /upload which is same as the one we mentioned while creating HTML form in Step 1.


1 Answers

Thx to @Pengtuzi I solved it:

I used the FormData API to upload the files. My mistake was that I thought the error would happen on the server.

Here's the code that solved it for me:

function uploadFiles(files) {
    var xhr = new XMLHttpRequest();
    var formData = new FormData();
    xhr.onload = successfullyUploaded;
    xhr.open("POST", "http://localhost:3000/upload", true);
    xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
    for(var file in files) {
        formData.append("uploads", files[file].data);
    }
    xhr.send(formData);
}
like image 131
lehnerchristian Avatar answered Oct 24 '22 08:10

lehnerchristian