How to upload files using multer in Node.js? - javascript

I want to upload images using multer. But it is not working. What is wrong here?
This code is in my route file.
var multer = require('multer');
var upload = multer({ dest: 'public/uploads/' });
And this is my post route.
router.post('/addNewFood', upload.single('avatar'),function (req, res, next) {
console.log(req.files);
});

Try this, it works for me. Used express and node.
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/uploads/')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
});
var upload = multer({ storage: storage }).single('avatar');
router.post('/addNewFood', //Your authentication check,//
function (req, res, next) {
upload(req, res, function(err) {
if (err) {
res.redirect(req.headers.referer + "/error.html");
return;
}
if (!req.files) {
res.redirect(req.headers.referer + "/error.html");
return;
} else {
//Implement your own logic if needed. Like moving the file, renaming the file, etc.
res.redirect(req.headers.referer);
}
});
}
);

Make sure you install the package
npm install --save multer
You can try the following way,
In the server side, In your routes or controller file configure the multer:
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/images/uploads')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' + file.originalname)
}
})
var upload = multer({ storage: storage });
In the storage object,
destination is stand for, where the file will be uploaded. So make sure in your project directory, /public/images/uploads path is created. Otherwise you may want to change the file path.
Also in storage object filename is stands for, what will be the uploaded file name. Here I add the current time with the original file name to make the all file name unique.
Now in your desired routing, suppose
router.post('/', upload.single('image'), (req, res) => {
//here your other task.
});
Now your file is uploaded. Make sure the client side is using the same name, In this case 'image'.
<input type="file" name="image" id="image" class='form-control'>
This is a single file upload procedure.
For multiple files
router.post('/', upload.array(), function (req, res, next) {
//your task goes here
});
For more information, check this link.

const multer = require("multer");
function fileFilter(req, file, cb) {
if (file.mimetype === "image/jpeg" || file.mimetype === "image/jpg" || file.mimetype === "image/png") {
cb(null, true)
} else {
cb(null, false)
}
cb(new Error('I don\'t have a clue!'))
}
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
cb(null, file.fieldname + '-' + uniqueSuffix)
}
})
var upload = multer({
storage: storage, limits: {
fieldSize: 1024 * 1024 * 5,
fileFilter: fileFilter
}
})
router.post("/", upload.single("image_url"),(req, res) => {
const new User=new User({
image_url: req.file.path
})

Related

i get 'Error: ENOENT: no such file or directory' when i upload file to the server [duplicate]

This is error which am getting while post data and file.
I have followed 'academind' tutorial for building Restful API services, also i have been searching answer for this type of errors but nothing works for me.
Am using "multer" to upload file
The folder 'uploads' available in the folder but it shows
ENOENT: no such file or directory, open 'D:\project\uploads\2018-01-24T07:41:21.832Zcheck.jpg'"
app.js
const express = require("express");
const app = express();
const morgan = require("morgan");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const productRoutes = require("./api/routes/products");
mongoose.connect('',
(err)=>{
if(err){console.log(err)}
else{console.log('DB Connected')}
})
mongoose.Promise = global.Promise;
app.use(morgan("dev"));
app.use('/uploads', express.static('uploads'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
);
if (req.method === "OPTIONS") {
res.header("Access-Control-Allow-Methods", "PUT, POST, PATCH, DELETE, GET");
return res.status(200).json({});
}
next();
});
// Routes which should handle requests
app.use("/products", productRoutes);
app.use((req, res, next) => {
const error = new Error("Not found");
error.status = 404;
next(error);
});
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
module.exports = app;
product.js
const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const multer = require('multer');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads/');
},
filename: function(req, file, cb) {
cb(null, new Date().toISOString() + file.originalname);
}
});
const fileFilter = (req, file, cb) => {
// reject a file
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: fileFilter
});
router.post("/", checkAuth, upload.single('productImage'), (req, res, next) => {
const product = new Product({
_id: new mongoose.Types.ObjectId(),
name: req.body.name,
price: req.body.price,
productImage: req.file.path
});
product
.save()
.then(result => {
console.log(result);
res.status(201).json({
message: "Created product successfully",
createdProduct: {
name: result.name,
price: result.price,
_id: result._id,
request: {
type: 'GET',
url: "http://localhost:3000/products/" + result._id
}
}
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
module.exports = router;
in product.js:
After new Date().toISOString() add replace() to change ":" to an accepted character.
Windows OS doesn't accept files with a ":"
The person on Youtube is using MAC OS
E.g
new Date().toISOString().replace(/:/g, '-')
Try the following:
Require this as a constant (const path = require('path');)
Change this line
cb(null, './uploads/');
With this:
cb(null, path.join(__dirname, '/uploads/'));
As I can see, you are trying to get a path that is not on served on the server, but rather a path that is on the server machine.
UPDATE
Try also changing this
app.use('/uploads', express.static('uploads'));
To this:
app.use(express.static(__dirname));
In order to expose the __dirname for static files.
This what worked for me. I changed './uploads/' into '__dirname' so that it can find the correct directory/filename anywhere on your computer.
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, __dirname);
},
filename: function(req, file, cb) {
cb(null, new Date().toISOString() + file.originalname);
}
});
Because when you set a specific folder name/directory you limit your image directory to be only or should be in that folder.
So the answer is in the tutorials comments section on youtube.
Instead of:
cb(null, new Date().toISOString() + file.originalname);
do:
cb(null, Date.now() + file.originalname);
Simple as.
I am doing the same course and I too had the same problem (i also use windows machine). The following worked for me:
const hash = require('random-hash'); // you have to install this package:
const fileStorage = multer.diskStorage({
destination: (req, file, callback) => { //this is storing the file in the images folder
callback(null, path.join(__dirname, '/Images'));
},
filename: (req, file, callback) => { //this is just setting a unique filename
let temp = file.originalname.split('.');
const filename = temp[0] + '-' + hash.generateHash({length: 5}) + '.' + temp[1]
callback(null, filename);
}
});
This creates a unique hash for the filenames as well
I found this in the comments section, here: https://www.youtube.com/watch?v=srPXMt1Q0nY&list=PL55RiY5tL51q4D-B63KBnygU6opNPFk_q&index=10
OK guys, in case someone has an issue with this in the file creation
stage, that probably means you're working on Windows. Now, you don't
need to feel discouraged and throw your computer to the trash (I
actually like always having to find workarounds for my Windows :).
There's at least a solution, and this is the one I found. My problem
is the file does not get created because Windows does not accept
filenames with colon (':') on it. My solution is rather simple. After
I get the current date, I use replace() and a regexp to change that
into a dash. Viola. It works!
Just in case, this is one way to do it:
filename: function(req, file, cb){
const now = new Date().toISOString();
const date = now.replace(/:/g, '-');
cb(null, date + file.originalname); }
Hope it helps someone who´s working in windows.
I came across the same error while saving the file.
The path I provided in callback didn't exist already that's why I got that error
const fs = require('fs');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
fs.mkdir('./uploads/',(err)=>{
cb(null, './uploads/');
});
},
filename: function(req, file, cb) {
cb(null, new Date().toISOString() + file.originalname);
}
});
With filesystem I created the same folder, In case of folder exists the err gets value but here nothing to worry about as we have that folder.
This worked for me. hope this would help
I had a similar error and this is how I resolved it. After using the replace method, I changed './uploads/images/' to 'uploads/images'. In this case, multer created the folder automatically. So you have something like this
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, 'uploads/');
},
filename: function(req, file, cb) {
cb(null, new Date().toISOString().replace(/:/g, '-')+ file.originalname);
}
});
For Windows users.
every thing is fine. problem is on this line
cb(null, new Date().toISOString() + file.originalname);
simply write cb(null,file.originalname);
it will work. try to use in different way to add the date string with file name.
You don't have permission to access /uploads/ on this server.
Try the following:
sudo chmod -R 777 /uploads
You should change the file name. Because ':' is not allowed in Windows.
Eg:
const storage = multer.diskStorage({
destination: function(req, file, cb){
cb(null,'./uploads/');
},
filename: function(req,file,cb){
cb(null, new Date().toISOString().replace(/:/g, '-') +'-'+ file.originalname);
}
});
I think if you work with Windows OS, you should use another methods of Date().i write code like this:
filename:(req,file,cb)=>{ cb(null,new Date().toDateString()+file.originalname) }
create folder uploads near app.js file
for this line
app.use('/uploads', express.static('uploads'));
if this can't find a folder then you can create one
destination: function(req, file, cb) {
fs.mkdir('./uploads/',(err)=>{
cb(null, './uploads/');
});
},
use this = > cb(null, Date.now() + file.originalname); instead of cb(null, new Date().toISOString() + file.originalname); to prevent
"error": "ENOENT: no such file or directory
This error occurs because ./uploads/ does not exist.
FYI :
If you use multer like below
const upload = multer({ dest: 'uploads' })
This creates uploads directories at server starting.
but if we use destination object then it does not create directory.
Proof/ref:
https://www.npmjs.com/package/multer#diskstorage
Solution
const fs = require('fs'); // Added to create directories
const multer = require('multer');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
// :::::::::::::::Create diretories:::::::::::::::::::
fs.mkdir('./uploads/',(err)=>{
cb(null, './uploads/');
});
},
filename: function(req, file, cb) {
cb(null, new Date().toISOString() + file.originalname);
}
});
const fileFilter = (req, file, cb) => {
// reject a file
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: fileFilter
});
What worked for me:(Windows OS)
const path = require("path");
const multer = require("multer");
const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, path.join(__dirname, "Images"));
//Images is folder which will hold uploaded images
},
filename: (req, file, cb) => {
cb(null, new Date().toISOString().replace(/:/g, "-") + file.originalname);
},
});
app.use(multer({ storage: fileStorage }).single("image")); //Middleware
Note: In order to remove all special character, we can use replace function as
const cleanVariable = mixSpecialCharters.replace(/[`~!##$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
-cb(null, './uploads/');
+cb(null, 'upload/');
},
filename: function(req, file, cb) {
cb(null, new Date().toISOString() + file.originalname);
}
});
in product.js just replace cb(null, new Date().toISOString()+ file.originalname) with cb(null, Date.now() + "-" + file.originalname);
Going out on a limb here, many other people are very close and I'm sure that some of the answers work for some people, but nothing short of this answer I found here has worked for me (struggled with this for 2 weeks now).
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.resolve(__dirname, './test'))
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
just change
cb(null, new Date().toISOString() + file.originalname);
with
cb(null, Date.now() + file.originalname);
Here is how you can avoid any directory issues
const path = require("path");
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, "../uploads"));
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
cb(null, file.fieldname + "-" + uniqueSuffix + file.originalname);
},
});
const storage = multer.diskStorage({
destination: function(req,file,cb){
//if that dir is not created then this will create that dir first
fs.mkdir('./uploads/',(err)=>{
cb(null,'./uploads/');
})
},
filename: function(req,file,cb)
{
cb(null,new Date().toISOString().replace(/:/g, '-') +'-'+file.originalname);
}
})
this happens in windows and in mac due to ':' so just replace it
As others suggest it is indeed an issue with how the OS is handeling parts of the date string, namely the ':'.
The purpose of this new Date().toISOString() is generating some randmoness, which can also be achieved with another 3rd party package like UUID for example:
filename: (req, file, cb) => cb(null, `${uuidv4()}-${file.originalname}`)
of course to use this library you have to install it and then refer it:
const { v4: uuidv4 } = require("uuid")
`const path = require("path");
const multer = require("multer");
const dir = __dirname;
const fileStorage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.extname(dir + "/public/my-uploads"));
},
filename: function (req, file, cb) {
cb(null, Date.now() + "-" + file.originalname);
},
});
module.exports = { fileStorage };
`
This Worked for me.
try
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, path.join(__dirname,'../uploads/');
},
filename: function(req, file, cb) {
cb(null, Date.now() + file.originalname);
}
});
also for filename change new Date() into Date.now()
Try to change the dist folder from ./uploads/ to uploads/
in this function
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads/');
},
filename: function(req, file, cb) {
cb(null, new Date().toISOString() + file.originalname);
}
});

Receiving multiple images using multer in NodeJS problem

I'm using multer package to receive multiple images from the frontend (ReactJS).I'm sending in additional to basic fields, an array of Images and I want to save them In my Rest API server using node.
I'm receiving my body fields but the problem is the images are not received. Here is my code:
const multer = require('multer');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads/');
},
filename: function(req, file, cb) {
cb(null, new Date().toISOString() + file.originalname);
}
});
const fileFilter = (req, file, cb) => {
if(file.mimetype === 'image/jpeg' || file.mimetype === 'image/png'){
cb(null, true);
} else {
cb(new Error('worng file format'), true);
}
}
// initialize multer
const upload = multer(
{
storage: storage,
fileFilter: fileFilter,
}
);
router.get('/', categoryController.getCategories);
router.post('/', upload.array('images', 3), (req, res, next) => {
try {
// here I want the images to save their location
console.log(req.files);
const name = req.body.name;
const description = req.body.description;
} catch (err) {
}
});
Here is how I'm sending the images array:
The folder upload where my images should be, is empty;
So, how do I save my multiple images ?
Append each file individually to the form:
for (const file of selectedFiles) {
formData.append('image', file);
}

req.files is empty when using multer in express app

I am trying to upload different types of files to server using multer in an express application. But every time server responds by stating TypeError: req.files is not iterable . I checked and req.files is empty.
Here is the code for the same:
var express = require('express');
var app = express();
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' + file.originalname)
}
})
var upload = multer({ storage: storage }).array('userfiles', 10);
app.post('/upload', function (req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
// A Multer error occurred when uploading.
return res.status(500).json(err);
} else if (err) {
// An unknown error occurred when uploading.
return res.status(500).json(err);
}
let uploadedFiles = [];
for (let item of req.files) {
uploadedFiles.push({ filename: item.originalname });
}
// Everything went fine.
res.json({ progress: 100, files: uploadedFiles });
})
});
app.listen(8000, (err) => {
if (err) {
console.log('ERROR:', err);
} else {
console.log('working on http://localhost:8000');
}
})
And this is how I am calling this API from postman:
Postman UI
I am unable to figure out where the problem is. Please help me with this.
I ran his code and he tried to store the images at the root of my filesystem.
to refer a a path relative to your current directory you need to use ./
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/') // change 'upload/' to './uṕload'
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' + file.originalname)
}
})
After this, the code worked.

uploading file with multer

I am a js-newbie and I am currently trying to use multer to upload some files.
Here is my code:
let express = require('express');
let im = require('imagemagick');
let gm = require("gm").subClass({
imageMagick: true
});
let multer = require('multer');
let app = express();
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
var upload = multer({storage: storage}).single('avatar');
app.post('/', function (req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
res.json({
success: false,
message: 'error during uploading'
});
} else if (err) {
res.json({
success: false,
message: 'error during uploading'
});
}
res.json({
success: true,
message: 'Image uploaded'
});
})
})
app.listen(3000);
When I send a post-req with a file (form-data), then I get a success message, however the folder with the file is not created:
post request
EDIT:
I managed to upload the file... I had to change the path of the uploads directory in the code like this:
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
});
However the uploads directory hast to be created manually, it is not being created automatically if it is missing...how do I solve this problem?
You can check this issue out:
https://github.com/expressjs/multer/issues/287
It says you should create a directory in 'destination' or as pre-requirements.

multer file upload not working

routes.js
module.exports=function(app, upload){
var postingsController=require('../controllers/postings.server.controller');
app.post('/postings', postingsController.savePosting);
}
controller.js
var multer=require('multer');
exports.savePosting=function(req, res, next){
// this diskstorage function is not at all executed
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
console.log(file);
cb(null, file.filename + '.' + 'jpg');
}
});
var upload = multer({ storage: storage });
upload.single('attachment');
res.json({ message: "success" });
}
can someone tell me which line exactly uploads file. DO i write multer diskstorage configuration in main express configuration file or can i write any where. By the way i able to see json response which is from the line
Typically the middleware is created and inserted outside of any actual route handlers. For example:
routes.js
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
console.log(file);
cb(null, file.filename + '.' + 'jpg');
}
});
var upload = multer({ storage: storage });
module.exports = function(app, upload) {
var postingsController = require('../controllers/postings.server.controller');
app.post('/postings',
upload.single('attachment'),
postingsController.savePosting);
};
controller.js
exports.savePosting = function(req, res, next) {
// Use `req.file` to access attachment
if (req.file)
res.json({ message: "success" });
else // no file uploaded
res.json({ message: "failure" });
};
Multer is a middleware, which means it is added as a parameter to your route in most cases. So what the actual syntax would be like is:
app.post ("/postings", multer ({ ... }), postingsController.savePosting);
Multer gets called inbetween the request to "/postings" and the final function to do all the file work for you. It will then provide you with all the information via
req.files["fileInputName"]
in the following middlewares (your function is a "middleware", too).

Categories

Resources