Jakemmarsh Jakemmarsh - 22 days ago 11
Javascript Question

How to upload files from ReactJS to Express endpoint

In the application I'm currently working on, there are a couple of file forms that are submitted via

superagent
to an Express API endpoint. For example, image data is posted like so:

handleSubmit: function(evt) {
var imageData = new FormData();

if ( this.state.image ) {
imageData.append('image', this.state.image);
AwsAPI.uploadImage(imageData, 'user', user.id).then(function(uploadedImage) {
console.log('image uploaded:', uploadedImage);
}).catch(function(err) {
this.setState({ error: err });
}.bind(this));
}
}


and
this.state.image
is set like this from a file input:

updateImage: function(evt) {
this.setState({
image: evt.target.files[0]
}, function() {
console.log('image:', this.state.image);
});
},


AWSAPI.uploadImage
looks like this:

uploadImage: function(imageData, type, id) {
var deferred = when.defer();

request.put(APIUtils.API_ROOT + 'upload/' + type + '/' + id)
.type('form')
.send(imageData)
.end(function(res) {
if ( !res.ok ) {
deferred.reject(res.text);
} else {
deferred.resolve(APIUtils.normalizeResponse(res));
}
});

return deferred.promise;
}


And lastly, the file receiving endpoint looks like this:

exports.upload = function(req, res) {

req.pipe(req.busboy);

req.busboy.on('file', function(fieldname, file) {
console.log('file:', fieldname, file);
res.status(200).send('Got a file!');
});

};


Currently, the receiving endpoint's
on('file')
function never gets called and so nothing happens. Previously, I've tried similar approaches with multer instead of Busboy with no more success (
req.body
contained the decoded image file,
req.files
was empty).

Am I missing something here? What is the best approach to upload files from a (ReactJS) Javascript app to an Express API endpoint?

Answer

I think superAgent is setting the wrong content-type of "application/x-form-www-encoded" instead of "multipart/form-data" you can fix this by using the attach method like so:

request.put(APIUtils.API_ROOT + 'upload/' + type + '/' + id)
    .attach("image-file", this.state.image, this.state.image.name)
    .end(function(res){
        console.log(res);
    });

for more information about the attach method, read the documentation here: http://visionmedia.github.io/superagent/#multipart-requests

since this involves a nodejs server script i decided to make a github repo instead of a fiddle: https://github.com/furqanZafar/reactjs-image-upload

Comments