Got issue with upload and resize image in express js - javascript

var express = require("express"),
app = express(),
formidable = require('formidable'),
util = require('util'),
fs = require('fs-extra'),
qt = require('quickthumb');
// Use quickthumb
app.use(qt.static(__dirname + '/'));
app.post('/upload', function (req, res){
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
form.on('end', function(fields, files) {
/* Temporary location of our uploaded file */
var temp_path = this.openedFiles[0].path;
/* The file name of the uploaded file */
var file_name = this.openedFiles[0].name;
/* Location where we want to copy the uploaded file */
var new_location = 'uploads/';
fs.copy(temp_path, new_location + file_name, function(err) {
if (err) {
console.error(err);
} else {
console.log("success!")
}
});
});
});
// Show the upload form
app.get('/', function (req, res){
res.writeHead(200, {'Content-Type': 'text/html' });
var form = '<form action="/upload" enctype="multipart/form-data" method="post">Add a title: <input name="title" type="text" /><br><br><input multiple="multiple" name="upload" type="file" /><br><br><input type="submit" value="Upload" /></form>';
res.end(form);
});
app.listen(8080);
I am a fresher on node js and express js. I followed this guy's blog to upload and resize image. The above is the code part. The upload function is working. However, in terms of resize function, if I want to resize uploaded image, I got this error:
events.js:85
throw er; // Unhandled 'error' event
^
Error: spawn identify ENOENT
at exports._errnoException (util.js:746:11)
at Process._handle.onexit (child_process.js:1053:32)
at child_process.js:1144:20
at process._tickCallback (node.js:355:11)

Did you install imagemagick? Quickthumb requires it for work.

Related

TypeError: Cannot read property 'path' of undefined in Node js while uploading file

I am new to node js.
I was trying to upload a file, it is showing some path error. Below is my code.
var http = require('http');
var formidable = require('formidable');
var fs = require('fs');
http.createServer(function (req, res) {
if (req.url == '/fileupload') {
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
console.log(files);
var oldpath = files.filetoupload.path;
var newpath = '/var/www/html/Node-Js/img/' + files.filetoupload.name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.write('File uploaded and moved!');
res.end();
});
});
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<form action="fileupload" method="post" enctype="multipart/form-data">');
res.write('<input type="file" name="filetoupload"><br>');
res.write('<input type="submit">');
res.write('</form>');
return res.end();
}
}).listen(8080);
Here I have installed the formidable module.It's installed.
I am getting this below error, please have a look.
/var/www/html/Node-Js/file_upload.js:11
var oldpath = files.filetoupload.path;
^
TypeError: Cannot read property 'path' of undefined
at /var/www/html/Node-Js/file_upload.js:11:40
at IncomingForm.<anonymous> (/var/www/html/Node-Js/node_modules/formidable/lib/incoming_form.js:107:9)
at emitNone (events.js:106:13)
at IncomingForm.emit (events.js:208:7)
at IncomingForm._maybeEnd (/var/www/html/Node-Js/node_modules/formidable/lib/incoming_form.js:557:8)
at Object.end (/var/www/html/Node-Js/node_modules/formidable/lib/incoming_form.js:247:12)
at IncomingMessage.<anonymous> (/var/www/html/Node-Js/node_modules/formidable/lib/incoming_form.js:132:30)
at emitNone (events.js:106:13)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
You are getting null{} in the console.log(files) is the reason behind this particular error. Filesis coming null so the files.filetoupload will be undefined and that's why files.filetoupload.path can't be found. I would say please find why the files is coming null. Once you will be started getting data in files this error will be solved.
I had the same issue and after looking at the logs I realized that path and name don't exist under that name so try replacing :
var oldpath = files.filetoupload.path;
var newpath = '/var/www/html/Node-Js/img/' + files.filetoupload.name;
with :
var oldpath = files.filetoupload.filepath;
var newpath = '/var/www/html/Node-Js/img/' + files.filetoupload.originalFilename;
This worked for me so I hope it helps
use files[0]
var http = require('http');
var formidable = require('formidable');
var fs = require('fs');
http.createServer(function (req, res) {
if (req.url == '/fileupload') {
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
console.log(files);
var oldpath = files[0].filetoupload.path;
var newpath = '/var/www/html/Node-Js/img/' + files.filetoupload.name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.write('File uploaded and moved!');
res.end();
});
});
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<form action="fileupload" method="post" enctype="multipart/form-data">');
res.write('<input type="file" name="filetoupload"><br>');
res.write('<input type="submit">');
res.write('</form>');
return res.end();
}
}).listen(8080);
I faced same issue and after looking closely into my code, I found that I used different name to get files in server.js then the one I mentioned in html file
I named file element in HTML
name="invoices" // input type=file
In server.js is used
filetoupload
So, if anyone face similar issue please look into your code especially the name given to HTML elements.

Upload image to MongoDB with Nodejs and express

I'm trying to upload a image using multer in nodejs. I configured multer to save uploaded images in the "upload" directory and when the form is submitted, the image is sent to the directory as it should. But I'm trying to save the path to that image (req.file.path) to a mongodb database and this is not working. I'm new to nodejs and mongodb and I can't figure out what the problem is.
This is the error I get:
ObjectParameterError: Parameter "obj" to Document() must be an object, got assets\uploads\uploaded_file-1518264794720.jpg
at new ObjectParameterError (C:\xampp\htdocs\projets\NodeApp01\node_modules\mongoose\lib\error\objectParameter.js:23:11)
at model.Document (C:\xampp\htdocs\projets\NodeApp01\node_modules\mongoose\lib\document.js:55:11)
at model.Model (C:\xampp\htdocs\projets\NodeApp01\node_modules\mongoose\lib\model.js:59:12)
at new model (C:\xampp\htdocs\projets\NodeApp01\node_modules\mongoose\lib\model.js:3750:13)
Here is my index.js:
var express=require('express');
var app=express();
var fs=require('fs');
var multer=require('multer');
app.set('view engine','ejs');
app.use(express.static('assets'));
var mongo=require('mongoose');
mongo.connect('mongodb://username:pass#database...');
var schema=new mongo.Schema({
item:String
});
var model1= mongo.model('todomod',schema);
var storage = multer.diskStorage({
destination: 'assets/uploads/',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now()+ '.jpg')
}
})
var upload = multer({ storage: storage });
app.get('/',function(request,response){
response.render('index.ejs');
});
app.get('/add_item',function(request,response){
response.render('add_item.ejs');
});
app.post('/add_item',upload.single('uploaded_file'),function(req,res){
console.log(req.body);
console.log(req.file);
model1(req.file.path).save(function(err,data){
if(err) throw err
res.json(data);
})
});
app.listen(80);
console.log('Application listening on port 80....');
And here is my view (.ejs) for the form:
<body>
<% include partials/navigation.ejs %>
<h1>Adding an item to the shop</h1>
<form id="theform" action="add_item" method="POST" enctype="multipart/form-data">
Name of item:<input type="text" name="item" class="thedata"><br>
<br>
Photo of item:<input type="file" name="uploaded_file" class="thefile">
<button type="submit">Add item</button>
</form>
</body>
The issue is you are passing uploaded file path instead of file object, You can do like this to save uploaded file path in mongodb:
let db_data = {
item : req.file.path
};
model1(db_data ).save(function(err,data){
if(err) throw err
res.json(data);
})

req.file is undefined (multer, node.js)

I've been trying to upload an image for a while now, but req.file is still undefined. Can someone see why?
this is my page. I am able to pick an image when I click the '+' glyphicon, but on the server side req.file is still empty.
EJS file
input[type="file"] and input[type="submit"] have css styles display: none
<form action="/profile/addProfilepicture" method="post" id="form" enctype="multipart/form-data">
<span id="upload" class="glyphicon glyphicon-plus-sign"></span>
<label for="profilePic"></label>
<input id=profilePic type='file' />
<input type="submit">
</form>
<img class="profileImg"
src="<%="images/pexels-photo-370799.jpeg"%>"
alt="fail">
Client JS file
When I click the '+'glyphicon it lets me pick an image. When I do this, this will trigger the form to submit and send a post request.
$("#upload").on('click',function() {
$("input[type='file']").click();
});
$('input[type="file"]').change(function (e) {
$("input[type='submit']").click()
});
server side JS
On the server side it stops at:
TypeError: Cannot read property 'filename' of undefined
at C:\Users\Tijl Declerck\Desktop\projects\digitalNomadApp\routes\profile.js:27:38
at Immediate._onImmediate (C:\Users\Tijl Declerck\Desktop\projects\digitalNomadApp\node_modules\multer\lib\make-middleware.js:53:37)
at runCallback (timers.js:793:20)
at tryOnImmediate (timers.js:751:5)
at processImmediate [as _immediateCallback] (timers.js:722:5)
The console.logs I tried gave me this: req.body returns an empty object and req.file returns undefined.
var express = require('express');
var router = express.Router();
var multer = require('multer');
var User = require('../models/Users');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads/profilePics')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
var upload = multer({ storage: storage }).single('myImage');
router.post('/addProfilePicture', function (req, res) {
var profilePicUrl = '';
upload(req, res, function (err) {
if (err) {
// An error occurred when uploading
} else {
console.log(req.file);
profilePicUrl = req.file.filename;
User.update({username: req.user.username}, {'profilePic.uploaded': true, 'profilePic.link': profilePicUrl}, function(err, doc){
console.log('THIS IS DONE')
});
}
});
});
You have to provide a name to your file input and it should match the single method's name, this is from multer doc:
.single(fieldname)
Accept a single file with the name fieldname. The single file will be
stored in req.file.
This is not well documented but fieldname refers to input name attribute
EJS file
<input id='profilePic' name='myImage' type='file' />
Express
...
var upload = multer({ storage: storage }).single('myImage');
...

Node.js parsing form data using formidable

Hey guys I am new to node, and trying to setup a file/image upload script.
I was able to setup node on my VPS and following this example I also set up the app and it is working great.
https://coligo.io/building-ajax-file-uploader-with-node/
It is using formidable and express
However I'd love to also parse a form where people can add their name and the files get uploaded into a folder containing their names.
I was able to get the folder creation working using mkdirp, however even after many hours of research (formidable api, express api, and more) I can't get the form to parse the name.
I suspect that the upload.js (which sends the data to the node app) does not work.
At the moment a new folder with a random string is created for each upload, but I'd love to be able to parse the entered formname.
Any idea how to get it working? I'd appreciate any help/hints.
app.js
var express = require('express');
var app = express();
var path = require('path');
var formidable = require('formidable');
var fs = require('fs');
var mkdirp = require('mkdirp');
var crypto = require("crypto");
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', function(req, res){
res.sendFile(path.join(__dirname, 'views/index.html'));
});
app.post('/upload', function(req, res){
var ordner = crypto.randomBytes(20).toString('hex');
mkdirp('/home/myfolder/fileupload/'+ordner, function (err) {
if (err) console.error(err)
else console.log(ordner)
});
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = path.join(__dirname, '/'+ ordner);
form.on('file', function(field, file) {
fs.rename(file.path, path.join(form.uploadDir, file.name + Date.now()+'.jpg'));
});
form.on('field', function(field, userName) {
console.log(userName);
});
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
form.on('end', function() {
res.end('success');
});
form.parse(req);
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
Thanks
The upload.js is unchanged and I simply added another input to the view.
You can do this by sending the parameters through the POST like so
app.post('/upload/:userName', function(req, res){
var username = req.params.userName
mkdirp('/home/myfolder/fileupload/'+username, function (err) {
if (err) console.error(err)
else console.log(ordner)
});
The rest of your code pretty much stays the same.
EDIT: Your ajax would look something like this
var username = 'GetThisValueFromTheUser'
$.ajax({
url: '/upload'+username,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data){
console.log('upload successful!');
}
});
Note: You can send parameters by using /:parameter in your POST or GET requests, from then on it is easy to use those parameters however you want.

How to upload file using multer or body-parser

I am a NodeJS beginner, following along a book "Web Development with MongoDB and NodeJS". I am stuck at its chapter 6 with 'multer'. When I use multer for file uploads the server throws the following error:
/Users/fk / Documents / imageuploader / node_modules / express / lib / application.js: 209
throw new TypeError('app.use() requires middleware functions'); ^
TypeError: app.use() requires middleware functions
but when I replace it with bodyParser the server fires up but when I click the upload button it gives me the following error on the browser.
500 TypeError: Cannot read property 'file' of undefined
However, it is supposed to redirect me towards another page, where the uploaded file is shown.
Here is my bodyParser code, please see if I am using it correctly because it gives me "body-parser deprecated" at the starting of the server. I've seen other questions like mine and I followed but none of them really work.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser({
uploadDir: path.join(__dirname, '../public/upload/temp')
}));
Following code shows how I use multer, just in case if there is something I shouldn't be doing please let me know. Which one would be better in case of uploading files, body-parser or multer?
app.use(multer({
dest: path.join(__dirname, '../public/upload/temp')
}));
var saveImage = function() {
var possible = 'abcdefghijklmnopqrstuvwxyz0123456789',
imgUrl = '';
for (var i = 0; i < 6; i += 1) {
imgUrl += possible.charAt(Math.floor(Math.random() * possible.length));
}
var tempPath = req.files.file.path,
ext = path.extname(req.files.file.name).toLowerCase(),
targetPath = path.resolve('./public/upload/' + imgUrl + ext);
if (ext === '.png' || ext === '.jpg' || ext === '.jpeg' || ext === '.gif') {
fs.rename(tempPath, targetPath, function(err) {
if (err) throw err;
res.redirect('/images/' + imgUrl);
});
} else {
fs.unlink(tempPath, function() {
if (err) throw err;
res.json(500, {
error: 'Only image files are allowed.'
});
});
}
};
saveImage();
Preceding block of code is the logic that I am using to upload the file. In the error it is referring to 'file' as undefined which is in the following line in the saveImage function. It is unable to get the path and therefore throws error 500 according to the else part of the saveImage function. Why is 'file' undefined here? I dont get it.
var tempPath = req.files.file.path,
multer() returns a middleware generator that uses the settings you specified, so you cannot pass its return value directly to app.use(). You can see all of the types of middleware it can generate in the documentation, but typically the generated middleware are added at the route level instead of globally like the other body parsers. This is because you will typically pass in the name of the file field(s) that you will be expecting.
For example, this will accept a single file (along with any non-file fields) whose form field name is foo:
var upload = multer({
dest: path.join(__dirname, '../public/upload/temp')
});
// ...
app.post('/upload', upload.single('foo'), function(req, res) {
if (req.file) {
console.dir(req.file);
return res.end('Thank you for the file');
}
res.end('Missing file');
});
Also, body-parser does not currently export a multipart/form-data-capable middleware, so you cannot use that module for handling uploaded files (well, short of passing a base64-encoded string in an application/x-www-form-urlencoded form or something, but that's much less efficient).
Here is the basic code for file upload in MEAN please check
HTML
<form id="frmDoc" name="frmDocument" ng-submit="upload()" class="form-horizontal form-bordered" enctype="multipart/form-data" >
<fieldset>
<div class="form-group">
<label class="col-md-4 control-label" for="val_email">Document<span class="text-danger">*</span></label>
<div class="col-md-4">
<div class="input-group">
<input type="file" name="file" id='file' required="required" />
</div>
</div>
</div>
</fieldset>
<div class="form-group form-actions">
<div class="col-md-8 col-md-offset-4">
<button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-upload"></i> submit</button>
</div>
</div>
</form>
CLIENT SIDE CODE
app.controller ('myctrl',function($scope,$http){
$scope.upload = function () {
var file = angular.element(document.querySelector('#file')).prop("files")[0];
$scope.files = [];
$scope.files.push(file);
$http({
method: 'POST',
url: '/users/upload',
headers: { 'Content-Type': undefined },
transformRequest: function (data) {
var formData = new FormData();
formData.append('model', angular.toJson(data.model));
formData.append('file', data.files[0]);
return formData;
},
data: { model: { title: 'hello'}, files: $scope.files }
}).success(function (res) {
console.log(res)
});
}
});
SERVER SIDE CODE
var multer = require('multer');
var mkdirp = require('mkdirp');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
//var code = JSON.parse(req.body.model).empCode;
var dest = 'public/uploads/';
mkdirp(dest, function (err) {
if (err) cb(err, dest);
else cb(null, dest);
});
},
filename: function (req, file, cb) {
cb(null, Date.now()+'-'+file.originalname);
}
});
var upload = multer({ storage: storage });
router.post('/upload', upload.any(), function(req , res){
console.log(req.body);
res.send(req.files);
});
I corrected the code of the book "Web Development with MongoDB and NodeJS" as follows:
app.use(multer({dest:path.join(__dirname,'../public/upload/temp')}).any());
.
.
.
.
const tempPath = req.files[0].path, // Temporary location of uploaded file
ext = path.extname(req.files[0].originalname).toLowerCase(), // Get file extension of the uploaded file
targetPath = path.resolve(`./public/upload/${imgUrl}${ ext}`); // The final path for the image file
The other parts of code remained intact. It worked and I could upload image files.
Best wishes,
Mehrdad Sheikhan
Code for upload file using Multer and save it to local folder
api- call fileUpload function
fileUpload(req)
.then(uploadRes => {
console.log('uploadRes', uploadRes)
})
.catch(err => {
console.log('err', err)
})
Create file upload service
const multer = require('multer') // import library
const moment = require('moment')
const q = require('q')
const _ = require('underscore')
const fs = require('fs')
let dir = './public'
/** Store file on local folder */
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, dir)
},
filename: function (req, file, cb) {
let date = moment(moment.now()).format('YYYYMMDDHHMMSS')
cb(null, date + '_' + file.originalname.replace(/-/g, '_').replace(/ /g, '_'))
}
})
/** Upload files */
let upload = multer({ storage: storage }).array('files')
/** Exports fileUpload function */
module.exports = {
fileUpload: function (req) {
let deferred = q.defer()
/** Create dir if not exist */
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
console.log(`\n\n ${dir} dose not exist, hence created \n\n`)
}
upload(req, {}, function (err) {
if (req && (_.isEmpty(req.files))) {
deferred.resolve({ status: 200, message: 'File not attached', data: [] })
} else {
if (err) {
deferred.reject({ status: 400, message: 'error', data: err })
} else {
deferred.resolve({
status: 200,
message: 'File attached',
filename: _.pluck(req.files,
'filename'),
data: req.files
})
}
}
})
return deferred.promise
}
}

Categories