I'm making a web app that allows users to upload and search for a recipe. A user can upload a recipe by filling a form and press a button to perform a POST request. I managed to save the recipe object, but I can't assign an image to it. I tried to use Multer, but I get "underfined" when I do log(req.file). I followed YouTube tutorials which only had app.js and index.ejs and it works, so I don't know if it's my Ajax code causing the issue??!!.
I have main.handlebars and main.css, and I have a folder called uploads but still always get undefined in the terminal, below is part of my code:
THANKS!!
upload.handlebars:
<label for="Userphrase">Recipe Name:</label>
<input type = "text" name = "recipeName" id = "recipeName"><br>
<label>Upload an image:</label>
<div class="container">
<input name="myImage" type="file"<br>
</div>
.
.
.
<script type = "text/javascript" src = "/public/palindrome.js"></script>
Ajax, only the request is here since i do error checking before that:
$("form").submit(function(e){
$.ajax({
type: "POST",
url: "/upload",
data: obj,
success: function(data){
alert("recipe added successfully!");
},
dataType: "json"
});
}
index.js:
at the top i have:
const storage = multer.diskStorage({
destination: './public/uploads/',
filename: function(req, file, cb){
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
const upload = multer ({
storage: storage
}).single('myImage');
then inside the POST route i have:
router.post('/upload',(req,res)=>{
upload(req, res, (err) => {
if(err){
res.render('index',{
msg: err
});
}else{
console.log(req.file);
res.send('test');
}
});
You have to send image in form data like
var formData = new FormData();
formData.append('imageName', imageFile);
on node side user same name('imageName') for multer it will get image from it
for more to multer check
https://www.npmjs.com/package/multer
For simplicity's sake, just use HTML form with enctype set to multipart/form-data on the client side. On the server side, say you're using Node.js, the uploaded files can be found in the request provided you're using the multer middleware to parse the form data. That's it.
You need to append that file to formData and then send it to server
Javascript:
var formData = new FormData();
jQuery.each(jQuery('#fileUpload')[0].files, function (i, file) {
formData.append('file', file);
});
$.ajax({
type: 'POST',
url: //To your route eg: /saveImage,
data: formData,
contentType: false,
processData: false,
success: function (result) {
if (result.status != 0) {
console.log(result.message)
return;
}
console.log(result.message)
}
});
Now at your route use multer
Node
var multer = require('multer')
var path = require("path");
// Check for extension of image
const getExtension = file =>{
if (file.mimetype == "image/jpeg")
ext = ".jpeg"
else
ext =".png"
return ext;
}
//initialize multer
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, '../public/images'))
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + getExtension(file))
}
})
var upload = multer({storage:storage})
router.post('/saveImage', upload.single('file'), (req, res, next)=>{
if (req.file && req.file.mimetype != 'image/jpeg' && req.file.mimetype != 'image/png')
return res.json({
status:1,
message:"Please Choose JPG or PNG images"
})
if(req.file){
let iamge = "/images/" + req.file.filename
res.json({
status:0,
message:"Successfully saved",
path : image
})
}
})
Related
I'm struggling uploading an image to a local folder using Node and Multer.
The response i get it's successfully, but the image don't save in the folder.
I have already lost a week trying to fix it
And yes, i have checked the destination route, in case you wonder.
This is my frontend:
<form id="tasasImage" enctype="multipart/form-data" style="display: flex; flex-direction: column;">
<input type="file" name="photo" id="photo" class="file"> <br>
<div id="uploadImg" class="btn btn-primary">ENVIAR</div>
</form>
<script>
$("#uploadImg").click(function () {
if ($('#photo').val().length > 0) {
var formData = new FormData($('#tasasImage')[0]);
console.log([...formData])
$.ajax({
url: "",
data: formData,
type: "POST",
processData: false,
contentType: false,
success: function(r){
console.log('Uploaded successfully');
$("#photo").val('');
},
error: function (e) {
console.log("some error", e);
}
});
}
</script>
And the backend:
var storageTasas = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, config.urlBase+'public/images/tasas');
},
filename: function(req, file, callback) {
var name = now+'-'+file.originalname;
callback(null, name);
}
})
var uploadTasas = multer({ storage: storageTasas }).single('photo');
const tasasUploadImage = (req, res) => {
uploadTasas(req, res, (err) => {
if (err) { console.error(err); }
else {console.log('Ssuccessfully Uploaded') };
})
res.send({'file': now});
}
router.post('/admin/aliados/tasas/:id', adminController.tasasUploadImage);
The url you are passing empty in the JQuery / Client script, it should be url : /admin/aliados/tasas/1234
The form data should be like this
var formData = new FormData($('#tasasImage'));
simple multipart file upload with express.js and multer with ajax
could you please tell me how to upload the file on some directory current example (uploads folder) .Here is my server side code
app.post('/upload', function (req, res) {
console.log('abcc')
upload(req, res, function (err) {
if (err) {
res.json({error_code: 1, err_desc: err});
return;
}
res.json({error_code: 0, err_desc: null});
});
});
full code node js
https://repl.it/repls/LustrousCharmingCommunication
I used this server and hit the service using client and upload only attached file
here is my request client code
https://jsbin.com/luwezirive/edit?html,js,output
$(function () {
$('.submit').on('click', function (e) {
e.preventDefault();
e.stopPropagation();
if ($('#fileId').val().length === 0) {
alert('please insert file')
} else {
var form = $('#fileUploadForm')[0];
// Create an FormData object
var data = new FormData(form);
console.log('fffff')
$.ajax({
url: 'https://lustrouscharmingcommunication--five-nine.repl.co/upload',
type: 'POST',
data: data,
cache: false,
enctype: 'multipart/form-data',
dataType: 'json',
processData: false, // Don't process the files
contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function (data, textStatus, jqXHR) {
console.log('succsss');
if (typeof data.error === 'undefined') {
// Success so call function to process the form
}
else {
// Handle errors here
console.log('ERRORS: ' + data.error);
}
},
error: function (jqXHR, textStatus, errorThrown) {
// Handle errors here
console.log('ERRORS: ' + textStatus);
// STOP LOADING SPINNER
}
});
}
})
})
I am getting success but file is not uploaded why ?
upload method
var storage = multer.diskStorage({ //multers disk storage settings
destination: function (req, file, cb) {
cb(null, './uploads/')
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length - 1])
}
});
var upload = multer({ //multer settings
storage: storage
}).single('file');
any update ?
The simplest way is using multer. https://github.com/expressjs/multer
Example taken from the documentation:
var express = require('express')
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
var app = express()
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any
})
I am trying to upload a file to my server, but req.file and req.files is always undefined on my POST REST endpoint.
The content I'm trying to upload is a ".dat" file, and I am expecting a json response.
Here's my code:
Server side:
var express = require('express');
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
var app = express()
app.post('/creoUpload', upload.single('uploadFileField'), function(req, res, next) {
console.log("req.file = ",JSON.stringify(req.file)); //is undefined
console.log("req.files = ",JSON.stringify(req.files)); //also undefined
});
Client Side:
<form id="creoUploadForm" action="/creoUpload" enctype="multipart/form-data" method="post">
<input type='file' name='uploadFileField'><br><br>
<input type='submit' value='Upload'/>
</form>
JS:
$( "#creoUploadForm" ).submit(function( event ) {
event.preventDefault();
var formData = new FormData($(this)[0]);
$.ajax({
url: '/creoUpload',
type: 'POST',
data: formData,
async: true,
cache: false,
contentType: false,
processData: false,
success: function (returndata) {
console.log("RETURN DATA IS: ",returndata);
},
error: function (err) {
console.log("ERROR: ",err);
}
});
});
I keep playing around with the fields but it's not working.. anyone see what I'm doing wrong here?
I'm following the example from https://www.npmjs.com/package/multer
Versions:
Express Version: 4.12.0
Node Version: 6.5.0
JQuery: 1.12.1
Thank you!
You are using multer as a middleware, So before entering into your function and printing it has uploaded images to storage and removes record from req.files.
There are two ways you can access req.files.
Use multer as a function stated by finw3.
Another solution is:
//CODE STARTS
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/filepath')
},
filename: function (req, file, cb) {
let filename = 'filenametogive';
req.body.file = filename
cb(null, filename)
}
})
var upload = multer({ storage: storage })
//CODE ENDS
Now you can access files in req.body.file
I have the same issue, if you check the documentation on the Error Handling section there is another kind of implementation, that's the one that works for me. The code will be something like this:
var express = require('express');
var multer = require('multer');
var upload = multer({ dest: 'uploads/' });
var app = express();
app.post('/creoUpload', function(req, res, next) {
upload(req, res, function (err) {
if (err) {
// An error occurred when uploading
console.log('Err: ', err);
return;
} else {
console.log('req.file: ', JSON.stringify(req.file));
console.log('req.files: ', JSON.stringify(req.files));
return;
}
})
});
Don't set contentType to false, as POST method requires contentType = 'w-xxx-form-urlencoded', which is the JQ default.
If the req.file and req.files are undefined, then the problem is that multer did not receive the uploaded file and this issue seems related to jQuery.
Uploading a FormData with jQuery 'v1.12.1' is not supported and it won't send anything at all.
I will recommend to try with fetch Api or change the version of your jQuery to 3.3.1.
I already tested the code and I have successfully upload a file to my server when I change my jQuery version from v1.12.1 to v3.3.1.
I have a really quick question:
I have an img tag (in my template file) that holds an image and in my Angular Controller I call:
var image = document.getElementById('srcImage');
I want to send this image ^ to the backend (I am using REST). The url I would use for this POST method is:
'/api/v1/images/addImage'
I've tried ng-file-upload and $http.post, but nothing seems to be working. Is there any way that I can simply send this image over to the server so I can store it in a database or file system? I am open to any solutions to making this happen.
Thanks!!
You can use below libraries, they have good documentation also
For Frontend -
https://github.com/nervgh/angular-file-upload
For Backend -
https://github.com/expressjs/multer
Sample Snippet -
In HTML :
<input type="file" nv-file-select="" uploader="ctrl.uploader" multiple />
Angular Controller :
vm.uploader = new FileUploader({
url: 'http://' + SERVER_URL + '/upload',
formData: [{
id: 1
}]
});
vm.save = function() {
vm.uploader.onBeforeUploadItem = function (item) {
console.log(item);
/* some action */
};
vm.uploader.onSuccessItem = function (item, imgResponse, status, headers) {
console.log(item);
console.log(imgResponse);
console.log(status);
console.log(headers);
/* some action */
};
};
Node Server :
var fs = require('fs');
var multer = require('multer');
var fileName = '';
var storage = multer.diskStorage({
destination: function (req, file, cb) {
var dirPath = 'path/to/save/file'
if (!fs.existsSync(dirPath)) {
var dir = fs.mkdirSync(dirPath);
}
cb(null, dirPath + '/');
},
filename: function (req, file, cb) {
var ext = file.originalname.substring(file.originalname.lastIndexOf("."));
fileName = Date.now() + ext;
cb(null, fileName);
}
});
// Assuming Express -
app.get('/upload', function (req, res) {
var upload = multer({
storage: storage
}).array('file', 12);
upload(req, res, function (err) {
if (err) {
// An error occurred when uploading
res.json(err);
}
res.json(fileName);
});
});
You can try multipart/form-data like this:
<form id = "uploadForm"
enctype = "multipart/form-data"
action = "/api/photo"
method = "post"
>
<input type="file" name="userPhoto" />
<input type="submit" value="Upload Image" name="submit">
</form>
I created a node.js server that uses busboy to take requests, and pipe the files to Imgur for upload. However, I keep getting an "Uploading file too fast!" response from Imgur, and I'm not sure exactly what the problem is. Here is the code snippet involving busboy:
var express = require('express');
var Busboy = require('busboy');
var fs = require('fs');
var request = require('request-promise');
var router = express.Router();
router.post('/u', function(req, res, next) {
var busboy = new Busboy({headers: req.headers});
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
if(fieldname == 'image') {
var options = {
uri: 'https://api.imgur.com/3/image',
method: 'POST',
headers: {
'Authorization': 'Client-ID ' + clientID // put client id here
},
form: {
image: file,
type: 'file'
}
};
request(options)
.then(function(parsedBody) {
console.log(parsedBody);
})
.catch(function(err) {
console.log(err);
});
}
});
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
console.log('field');
});
busboy.on('finish', function() {
res.status(200).end();
});
req.pipe(busboy);
});
As you can see I'm piping the request file directly into my request for imgur. Providing a ReadStream by simply saving the file to disc and then using fs.createReadStream() works perfectly, so I'm not really sure why trying to pipe directly from request to request gives me the error. The exact response I'm getting from Imgur is:
StatusCodeError: 400 - {"data":{"error":"Uploading file too fast!","request":"\/3\/image","method":"POST"},"success":false,"status":400}
If anyone has encountered this before, it would be helpful...
The first issue is that you should be using formData instead of form for file uploads. Otherwise, the request library won't send the correct HTTP request.
The second issue is that the stream object won't have the correct content length until it's fully processed. We can buffer the data ourselves and pass it after the initial file stream from busboy has processed.*
This gives us something that looks like
var express = require('express');
var Busboy = require('busboy');
var fs = require('fs');
var request = require('request-promise');
var router = express.Router();
router.post('/u', function(req, res, next) {
var busboy = new Busboy({headers: req.headers});
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
if(fieldname == 'image') {
// the buffer
file.fileRead = [];
file.on('data', function(data) {
// add to the buffer as data comes in
this.fileRead.push(data);
});
file.on('end', function() {
// create a new stream with our buffered data
var finalBuffer = Buffer.concat(this.fileRead);
var options = {
uri: 'https://api.imgur.com/3/image',
method: 'POST',
headers: {
'Authorization': 'Client-ID ' + clientID // put client id here
},
formData: {
image: finalBuffer,
type: 'file'
}
};
request(options)
.then(function(parsedBody) {
console.log(parsedBody);
})
.catch(function(err) {
console.log(err);
});
});
}
});
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
console.log('field');
});
busboy.on('finish', function() {
res.status(200).end();
});
req.pipe(busboy);
});
Code for the buffering is from http://thau.me/2014/02/nodejs-streaming-files-to-amazons3/
Lastly, you may want to consider using the request library, as the request-promise library discourages the use of streams. See the github repo for more details: https://github.com/request/request-promise