File upload and move problem with express-fileupload - node.js

I have this file/folder structure:
+--public
| +--/productsImg/ //folder where i want to move images
+--routes
| +--products.js //the part that tells the images to move to /public/productImg/
In order to move a specific image i have used EXPRESS-FILEUPLOAD module.
I want all the images to be in /public/productsImg/ folder. SEE the above for the folder/file structure.
In products.js i wrote the following code:
var image = req.files; // in VIEW <input type="file" name="image"/>
var uploadPath = path.resolve(__dirname, '../public/productsImg/' + image.name);
//console.log(uploadPath) gives nothing ;
image.mv(uploadPath, (err) => {
if (err) {
return res.status(500).send(err);
}
res.send('File uploaded to ' + uploadPath);
});
I have this error in nodemon console : POST /products/store 500 9.733 ms - 16104
I think may be i'm not using correctly the path.resolve part and my uploadPath variable (file) is unknow, i think.
Have seen other posts, i couldn't figure it out. Any ideas?

May be it can help someone: solution
1) Added var path = required('path'); in product.js eventhough i added this in my app.js. It is important otherwise it won't work.
2) Created /tmp/ folder (root of your project) and add this in app
app.use(fileUpload({
useTempFiles : true,
tempFileDir : '/tmp/'
}));
3) Changed the code to
var { image } = req.files;
var uploadPath = path.resolve(__dirname, '../public/productsImg/', image.name); // important
console.log(uploadPath);
image.mv(uploadPath, (err) => {
if (err) {
return res.status(500).send(err);
}
res.send('File uploaded to ' + uploadPath);
//or whatever you want to do
});

According to your example, your file object should be in req.files.image.
See express-fileupload documetnation:
Example:
You're uploading a file called car.jpg
Your input's name field is foo:
In your express server request, you can access your uploaded file from req.files.foo:
app.post('/upload', function(req, res) {
console.log(req.files.foo); // the uploaded file object
});

hie, in express-fileupload you access the image via the name attribute, so you might consider changing
var image = req.files
to
var image = req.files.image
hope it helps

Related

Sending image from server to use in EJS file

Making a basic blog with an admin section to learn the basics of node and express. I just implemented multer middleware to save images for a blog post to a folder ("images") on the server - not to mongo or an s3 bucket - keeping it simple for now to learn.
I am using EJS and using res.render to send and render the frontend. However, I want to put the image in the EJS file as well. I've tried simply passing in the filename like so:
res.render(path.resolve(__dirname, "../", "views", "posts.ejs"), {postData, file});
postData being the data on the post from the mongodb collection. All this does is send the filename itself which is not helpful.
I've looked around, but don't seem to find an answer to this, or I'm over thinking this?
Here is the rest of the code for the controller:
const path = require("path");
const fs = require('fs');
const Post = require('../models/modelPosts');
exports.getPost = (req, res, next) => {
const postPath = req.params.post;
Post.findOne({ postPath: postPath }, (error, postData) => {
if (error) { return next(error) };
if (postData.postReadyToView == true) {
// find the correct image
fs.readdirSync('./images').forEach(file => {
const stringOfFile = JSON.stringify(file);
const stringOfPathJPEG = JSON.stringify(postPath + ".jpeg");
const stringOfPathJPG = JSON.stringify(postPath + ".jpg");
const stringOfPathPNG = JSON.stringify(postPath + ".png")
// send the ejs file and image
if (stringOfFile == stringOfPathJPEG ||
stringOfFile == stringOfPathJPG ||
stringOfFile == stringOfPathPNG) {
res.render(path.resolve(__dirname, "../", "views", "posts.ejs"), {
postData, file
});
}
})
} else {
res.redirect(404, "/404");
}
})
};
Send the file path of the page to be rendered as data, register the image garden folder (ex: public/images) as a static folder using express.static in nodejs, and load the image when the file path is loaded in the rendering page. I think you can.

React & Node (Multer): Image is not found by path while it exists on that path

hello i have image uploading feature on my website, and it is uploaded in special folder with NodeJS (Express) and Multer but problem is that when user uploads that image he is redirected to freshly created route and on that route the image is supposed to display, but it does not even thought it exists
here is multer code:
const imgStorageBaseURL = '/images'
const imgStoragePath = path.join(__dirname, '..', 'images');
const storage = multer.diskStorage({
destination: (req, file, callback) => {
const userPath = path.join(imgStoragePath, req.userId);
fs.mkdir(
userPath,
() => callback(null, userPath)
)
},
filename: (req, file, callback) => {
const filenameParts = file.originalname.split('.');
const ext = filenameParts.pop();
const basename = filenameParts.join('.');
const additionalPath = Date.now() + '' + Math.floor(Math.random() * (2000 - 500)) + 500;
callback(null, basename + '-' + additionalPath + '.' + ext);
}
})
and here is array of that image links (to save that links into db)
var imgarray = []
req.files.forEach((file) => {
imgarray.push(imgStorageBaseURL + '/' + req.userId + '/' + file.filename)
console.log(imgarray)
})
and react code
{this.state.imageURLs.map((src, k)=>{
return (
<img src={src} key={k} alt="Hey" className="img"/>
)
})}
there is source in inspect element
and here is proof that image exists on that path
but when i visit that url in source i got this
what is the reason that causes this misunderstanding?
Thank You!
Although the image exists in the filesystem fine, it is not correctly placed "relative" to the web server i.e your React Application.
Usually images are placed in separate areas designated for static files.If you had used create-react-app to build your app, they can be accessed from the 'public' folder
render() {
// Note: this is an escape hatch and should be used sparingly!
// Normally we recommend using `import` for getting asset URLs
// as described in “Adding Images and Fonts” above this section.
return <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;
}
Here is the link to the official docs.
Specifically you should update your react code to:
{this.state.imageURLs.map((src, k)=>{
return (
<img src={process.env.PUBLIC_URL +src} key={k} alt="Hey" className="img"/>
)
})}
Just make sure to move the images or update the path where images get saved from multer/express to the public folder.

Should not allow file upload if anyone changes extension from exe to png via multer in node js application

I'm uploading file using multer in my nodejs (express js) application which is working fine. I have put a mime type check there also to allow only png files but if I change the ext of the uploaded file from abc.exe to abc.png it also gets uploaded which is wrong.
here is my code.
var multer = require('multer');
var imagefolder = __base + 'public/complaintimages/';
var diskstorage = multer.diskStorage({
destination: function (req, file, cb) {
if (common.ImageMimeTypes.indexOf(file.mimetype) < 0) {
common.ActionOutput.Status = common.ActionStatus.WrongFileUploaded;
common.ActionOutput.Message = 'Invalid image file: ' + file.originalname;
cb(new Error('FileUpload:' + common.ActionStatus.WrongFileUploaded), null);
} else
cb(null, imagefolder);
},
filename: function (req, file, cb) {
var filenm = randomstring.generate(10);
//console.log(filenm + file.originalname);
cb(null, filenm + file.originalname);
}
});
var upload = multer({
storage: diskstorage
});
It should check the file content for mime type. Renaming other into png should not be uploaded. It seems to be bug in the library.
Please advice.
In your route handler when you have the saved file name, you can use the mmmagic module:
var mmm = require('mmmagic'),
var magic = new mmm.Magic(mmm.MAGIC_MIME_TYPE);
magic.detectFile(fileName, function (err, mime) {
if (err) {
// handle error
} else {
// check the mime
// and remove the file if you don't like it
// plus send a correct response to the client
}
});
Update
If mmmagic doesn't work for you then you can use the file-type module but it works on buffers so you first will have to read the file (or some part of it) into a buffer and check the mime type with file-type. The read-chunk module can be handy to read part of the file.
See:
https://www.npmjs.com/package/file-type
https://www.npmjs.com/package/read-chunk

Which is the better approach to upload images via nginx?

I want to implement file uploading via nginx and FileAPI on client side. So I have the following questions:
Which is module better suite for this task nginx-upload-module or native clientbodyinfileonly or something else?
How to check that user is authenticated before uploading starts (maybe touch backend and return some data back to nginx like user_id)
How to rename file to hash to be looks like the following www.mysite.com/files/011/b0f/639/011b0f639f69491e9e4cbaf41656297f.jpg ?
How to make and save three copy of uploaded image several sizes (128x128, 96x96, 30x30)?
Which is module better suite for this task nginx-upload-module or
native clientbodyinfileonly or something else?
I just had a look at nginx-upload-module and this is a 7 years old nginx module to handle multipart requests. Nginx has been supporting multipart uploads for years now, so you do not need to change anything to your nginx setup as long as you're not running a 7 years old version!
For the remaining questions I'll give you an example, using :
Thumbnail to generate the thumbnails (You will need graphitemagick installed, but you can replace it with any other lib)
Q to easily generate the different thumbnails concurrently and have a clean code with no callback pyramid
Multer to handle the file upload server-side.
You could use other libraries to do the same thing, but this will show you one way to do it easily. For the sake of this example it is all in one single file.
var express = require('express');
var multer = require('multer');
var md5 = require('MD5');
var Q = require('q');
var Thumbnail = require('thumbnail');
var app = express();
var targetFolder = '/var/www/mysite/files/full/';
var thumbnailFolder = '/var/www/mysite/files/thumbs/';
var thumbnail = new Thumbnail(targetFolder, thumbnailFolder);
var makeThumbnail = Q.nbind(thumbnail.ensureThumbnail,thumbnail);
var thumbnailSizes = [30,96,128];
app.post('/upload', function(req,res,next) {
//Check the authentication here, this is the first middleware.
if(authenticated) {
next();
} else {
res.send(401);
}
}, multer({
dest: targetFolder,
rename: function (fieldname, filename) {
//Rename the file with it's name + date hash
return md5(filename + Date.now());
},
onFileUploadComplete: function(file, req, res) {
var resizePromises = [];
for(var i in thumbnailSizes) {
var p = makeThumbnail(file.name,thumbnailSizes[i],thumbnailSizes[i]);
resizePromises.push(p);
}
Q.all(resizePromises).done(function(){
// The file has been resized to the specified format.
res.send(200);
},function(err) {
console.log(err);
res.send(500);
// Error !
});
}
});

Storing the location of the images in the database using `VARCHAR` in ExpressJS & image in server Hard-Disk

How I can do this in ExpressJS?
Storing the location of the images in the database using VARCHAR
datatype instead of any BLOB or other binary datatype.
then store that image in server harddisk in possible image space
/public/images/
i am new to express
.
Any sample example to achieve this ?
What you can do is use the multipart middleware, which automatically streams the file uploads to the disk, and then provides a req.files object.
app.use('/upload', express.multipart({ uploadDir: '/public/images' }));
Once you've configured this, in your request handler, you can get the upload path (see multiparty's documentation, which is used internally by the multipart middleware):
app.post('/upload', function (req, res, next) {
// Assuming the field name of the file in the form is 'file'
var path = req.files.file.path;
connection.query('your mysql query', next);
});
you can try this for upload image you will store only path of image and save that image in your storage
var tempPath = req.files.image.path;
var ext = path.extname(req.files.image.name).toLowerCase();
var targetPath = path.resolve('./profile_img/' + user_id + ext);
// var targetPath = path.resolve('D:/Alex/Project/img/' + user_id + ext);
if (ext === '.png' || ext === '.jpg' || ext === '.jpeg' || ext === '.gif')
{
var inStr = fs.createReadStream(tempPath);
var outStr = fs.createWriteStream(targetPath);
inStr.pipe(outStr);
//save profile image to database
connection.query('update users set img_path=? where id=?',[targetPath,user_id],
function(err,imagesave){
if(!err)
{
console.log('Profile Picture Uploaded ..');
res.json({'code':200,'status':'Success','message':'Profile Picture Uploaded ..'});
return;
}
else
{
console.log('can not update ..',err);
res.json({'code':200,'status':'Success','message':err});
return;
}
});
}
else
{
console.log('File type must be image',err);
res.json(500, {error: 'Only image files are allowed.'});
}
}

Resources