File upload to nodejs using ajax - javascript

I am trying to upload image to nodejs server using ajax but it fails to get file.
Client Side
function sendFileToServer(file){
var formData = new FormData();
formData.append('profile_image',file,file.name);
$.ajax({
type: "POST",
url: "URL",
data: formData,
dataType:'json',
processData: false,
success: function (data) {
alert("Data Uploaded: "+data);
},
error : function(err){
alert(JSON.stringify(err));
}
});
}
$("#profile_image_2").change(function(){
var file = this.files[0];
sendFileToServer(file);
});
Server Side
var multer = require('multer');
var mime = require('mime-lib');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/upload/')
},
filename: function (req, file, cb) {
console.log("filename exte "+file.mimetype);
console.log(mime.extension(file.mimetype));
cb(null, Date.now() + '.' + mime.extension(file.mimetype)[0]);
//crypto.pseudoRandomBytes(16, function (err, raw) {
// cb(null, raw.toString('hex') + Date.now() + '.' + mime.extension(file.mimetype));
//});
}
});
var uploading = multer({ storage: storage });
router.post('/profile',uploading.single('profile_image') ,function(req,res){
if (req.file){
res.json("In here");
}else{
res.json("FILE DOES NOT EXIST");//ALWAYS ENDS UP HERE
}
});
When i try it in bare form it works fine, but not using ajax. Please help

Try to use jQuery Form Plugin. It will make this for you.

Related

Multer req.body empty in node js

I am using multer to upload form data( some image files).
But req.body and req.files both are coming empty. when I am uploading images I got the successful message " your image has been uploaded" but my folder is empty.
I tried all solution available on StackOverflow as well as GitHub.
but no luck.
below my code
form in the HTML file
<form id="uploadForm" enctype="multipart/form-data" action="multerFile" method="post">
<input type="file" name="userPhoto" multiple />
<input type="submit" value="Upload Image" name="submit">
<input type='text' id='random' name='random'>
<br>
<span id="status"></span>
</form>
<script>
$(document).ready(function () {
$('#uploadForm').submit(function () {
$("#status").empty().text("File is uploading...");
$(this).ajaxSubmit({
error: function (xhr) {
status('Error: ' + xhr.status);
},
success: function (response) {
console.log(response)
$("#status").empty().text(response);
}
});
return false;
});
});
</script>
index.js
app.post('/multerFile', function (req, res) {
console.log("hi i am multer function")
var storage = multer.diskStorage({
destination: 'C:/Users/chandra/Documents/project/node_project/public'
});
var upload = multer({ storage: storage }).array('userPhoto', 2);
upload(req, res, function (err) {
if (err) {
console.log(err);
return res.end("Error uploading file.");
} else {
console.log(req.body)
console.log(req.files);
req.files.forEach(function (f) {
console.log(f);
// and move file to final destination...
});
res.end("File has been uploaded");
}
});
});
I tried:
Express, Multer, BodyParser req.body empty array
multer req.body showing empty always
https://github.com/expressjs/multer/issues/351
https://github.com/expressjs/multer/issues/391
and I followed this tutorial for multer
https://codeforgeek.com/2016/01/multiple-file-upload-node-js/
I am unable to understand that what am I doing wrong?
please help.
Thanks in advance
First, .ajaxSubmit() is not core jQuery functions. You need the jQuery Form Plugin and I don't know if you import it like below:
<script src="http://malsup.github.com/jquery.form.js"></script>
The easiest way to do it will be to do it without a plugin like this:
$('#uploadForm').submit(function() {
$("#status").empty().text("File is uploading...");
var formData = new FormData($('#uploadForm')[0]);
$.ajax({
type: 'POST',
url: '/multerFile',
data: formData,
success: function(response) {
console.log(response)
$("#status").empty().text(response);
},
contentType: false, // Prevent jQuery to set the content type
processData: false // Prevent jQuery to process the data
});
return false;
});
Now in your backend, your destination should better be (with a folder uploads in your public folder):
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads/')
},
});
I just changed my storage to
const storage = multer.diskStorage({
destination: './public/uploads/',
filename: function(req, file, cb){
cb(null,file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
And it is workings fine..

File upload populating req.body but not req.file

I have created a file upload API using multer and express which works fine through POSTMAN but when i try to call the same api using another file upload API, it's not working:
My code is as follows which runs on http://localhost:7022/nuxeo/upload:
module.exports.upload = function (req, res, next) {
var path = req.body.path
var uploadFile = req.file; //get uploaded file
var stream = streamifier.createReadStream(req.file.buffer) //create a stream from file buffer
var blob = new Nuxeo.Blob({ //create a blob from file stream
content: stream,
name: uploadFile.originalname,
mimeType: uploadFile.mimetype,
size: uploadFile.size
});
var batch = nuxeo.batchUpload();
In the above code when I call the API through postman, my req.file is populated.
But calling the above API using the code below doesn't populate the req.file of the first API, it is undefined. I have also tried using form-data npm module without any luck :
module.exports.attach = function(req,res,next){
var uploadfile = req.file //file is populated here
formData = { 'file' : uploadfile, 'path' : '/FCA/DT/clause32a'}
var opts = {
url: "http://localhost:7022/nuxeo/upload",
headers: { 'enctype':  'multipart/form-data;boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' },
json: true,
body: formData
};
request.post(opts,function(err,response,body){
console.log(body)
})
}
module.exports.attach = function(req,res,next){
var uploadfile = req.file //file is populated here
var fs = require('fs');
var request = require('request');
request.post({
url: <URL>,
formData: {
file: fs.createReadStream(<FILE_PATH>),
filetype: <FILE_TYPE>,
filename: <FILE_NAME>,
title: <FILE_TITLE>,
},
}, function(error, response, body) {
console.log(body);
});
}
I solved it with the help of this post : how to upload file saved in memory by multer to another API
var stream = require('stream')
const { Duplex } = stream;
function bufferToStream(buffer) {
const duplexStream = new Duplex();
duplexStream.push(buffer);
duplexStream.push(null);
return duplexStream;
}
request.post({
headers: { 'enctype': 'multipart/form-data;boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' },
url: "http://localhost:7022/nuxeo/upload",
formData: {
file: {
value: bufferToStream(req.file.buffer),
options: {
filename: req.file.originalname,
contentType: req.file.mimetype,
knownLength: req.file.size
}
},
path: '/FCA/DT/clause32a'
}
}, function (error, response, body) {
if (error) { return next(error)
res.send(JSON.parse(body))
})

using ng-file-upload to upload file from client to node and multer at node js to upload file on server, get req.file undefined always

I am using ng-file-upload to upload file from angular client to node js and at server side I am using multer to upload, Problem is I am not getting any error in multer but file is not uploaded, I found req.file is undefined always.Thanks in advance.
I am sharing my code:
view:
<form name="uploadform" role="upload" enctype="multipart/form-data" ng-submit="uploadFile();">
<input type="file" placeholder="Browse" class="btn btn-sm btn-
default" accept="application/pdf,application/msword,application/excel"
ngf-select="onFileSelect($files)">
</form>
myController:
$scope.onFileSelect = function($files) {
$scope.uploadfile = $files;
console.log("onFileSelect $scope.uploadfile is "+$scope.uploadfile);
for (var i = 0; i < $files.length; i++) {
var $file = $files[i];
console.log("$file name is "+$file.name);
console.log("$file type is "+$file.type);
console.dir("$file is "+$file);
}
}
//After click on upload button following method get called and fot that Upload here is ng-upload-file
$scope.uploadFile = function(){
Upload.upload({
url: hostname+'/upload',
//file:$scope.uploadfile[0], //webAPI exposed to upload the file
data:{file:$scope.uploadfile[0]} //pass file as data, should be user ng-model
}).then(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
//upload function returns a promise
if(data.data.error_code === 0){ //validate success
$window.alert('Success ' + data.config.data.file.name + 'uploaded. Response: ');
} else {
$window.alert('an error occured');
}
});
}
Routing:
router.post('/upload',upload1);
In app.js:
var multer = require('multer');
var storage = multer.diskStorage({ //multers disk storage settings
destination: function (req, file, cb) {
console.log("come inside storage destination"+" file is "+file);
cb(null, './uploads/')
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
console.log("come inside filename");
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1])
}
});
var upload = multer({ //multer settings
storage: storage
}).single('file');*/
upload1: function(req, res) {
req.headers['content-type'] = 'multipart/form-data; boundary=something';
res.setHeader('Content-Type', 'applicaton/json');
/** API path that will upload the files */
console.dir("req is "+req);
req.headers['content-type'] = 'multipart/form-data; boundary=something';
res.setHeader('Content-Type', 'applicaton/json');
upload(req,res,function(err){
if(err){
res.json({error_code:1,err_desc:err});
return;
}
res.json({error_code:0,err_desc:null});
console.log("req.file" +req.file);
})
}
you should take the file as parameter in your function
$scope.uploadFile = function(file){
Upload.upload({
url: hostname+'/upload',
//file:$scope.uploadfile[0], //webAPI exposed to upload the file
data:{file:file} //pass file as data, should be user ng-model
}).then(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
//upload function returns a promise
if(data.data.error_code === 0){ //validate success
$window.alert('Success ' + data.config.data.file.name + 'uploaded. Response: ');
} else {
$window.alert('an error occured');
}
});
}

How to POST file via jQuery to nodejs connect-busboy

I can successfully send a file to connect-busboy by using an HTML form's action attribute like so:
<form ref='uploadForm' method="post" action="http://localhost:3000/fileupload" enctype="multipart/form-data" id='uploadForm'>
Select file to upload:
<input type="file" name="sampleFile">
<input type="submit" value="Upload!">
</form>
However, I would prefer to not have my page redirect.
I tried to convert this to jQuery by removing the action attribute in the form tag and adding an onclick function with the following:
$.ajax({
url:'http://localhost:3000/fileupload',
type:'post',
contentType: 'multipart/form-data',
data:$('#uploadForm').serialize(),
success:function(){
alert('Success');
},
error: function() {
alert('Error');
},
});
Unfortunately, this doesn't work with the error:
TypeError: Cannot read property 'end' of undefined
The Nodejs code is as follows:
const express = require('express');
const busboy = require('connect-busboy');
const app = express();
app.use(busboy());
const fs = require('fs');
app.post('/fileupload', function(req, res) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
fstream = fs.createWriteStream(__dirname + '/files/' + filen ame);
console.log(fstream);
file.pipe(fstream);
fstream.on('close', function () {
res.send('Success');
});
});
});
var port = process.env.PORT || 3000;
app.listen(port);
Full error: http://i.imgur.com/vUqmjWS.png
By explicitly serializing the form you are implicitly avoiding/removing the multipart/form-data format. Instead, pass a FormData instance as the data. You can instantiate a new FormData from an existing form like:
var data = new FormData($('#uploadForm')[0]);
$.ajax({
url: 'http://localhost:3000/fileupload',
type: 'POST',
contentType: false,
processData: false,
cache: false,
data: data,
success: function() {
alert('Success');
},
error: function() {
alert('Error');
}
});

How to send file in a request and download the file within the response without redirecting

I an trying to create a service which takes a xlsx template file and response a populated xlsx file with some values. What I have done so far is,
index.html
<input name="file" type="file" onchange="callthis()"/>
script.js
// callthis sends the file from client to server
function callthis() {
var formData = new FormData($(this).files[0]);
$.ajax({
url: '/uploadTemplate',
type: 'POST',
data: formData,
success: function (data) {
console.log(data);
alert(data)
},
cache: false,
contentType: false,
processData: false
});
}
serverRouter.js
router.post('/uploadTemplate', function(req, res, next){
let uploadedFilePath = null;
// I'm using multer for handling formdata in the server
var upload = multer({ dest: Locator.temp.temp });
//configure the multer
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, Locator.temp.temp);
},
filename: function (req, file, callback) {
uploadedFilePath = file.fieldname + '-' + Date.now() + '.xlsx';
callback(null, uploadedFilePath);
}
});
var upload = multer({ storage : storage}).single('file');
//in here i am uploading the file.
//and reading the file ugin XLSX modules.
//doing some changes to xlsx json object
//and write the data to a file in a temp folder
//i'm using res.download method to send downloadable file back to client
res.download(Path.join(Locator.temp.temp, uploadedFilePath));
});
})
Using above codes, i could upload the file and get response. success method prints out details i added with some unreadable characters. But i could not download the file.
How can i download the file. Are there any different and better approach for this situation.
You can't attach a download to an AJAX request. You will have to send the download URL in the AJAX response and then have your client side script open the URL
In the server:
let response = {downloadUrl: Path.join(Locator.temp.temp, uploadedFilePath)}
res.json(response)
In the client:
window.open(ajaxResponse.downloadUrl);

Categories