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
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..
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))
})
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');
}
});
}
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');
}
});
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);