upload files from different fields in a form using multer - node.js

I have a document that contains two fields are of input type="file" and I want to upload both of these on submit.
This post method giving me internal server error 500 on uploading two files but when I upload one file, it is OK.
router.post('/', mediaFiles.uploadSingle('icon_url'), mediaFiles.uploadSingle('background_url'),
async (req, res) => {
name: req.body.name,
icon_url: req.file.path.replace(/\\/g, "/"), // req.file['icon_url']
background_url: req.file.path.replace(/\\/g, "/") // req.file['background_url']
})
you can ignore this MediaFiles class because it provides traditional code to upload images with multer
import multer from "multer";
import path from "path";
class MediaFiles {
private storage = multer.diskStorage({
destination: 'uploads/',
filename: function (req, file, callback) {
callback(
null,
file.originalname.replace(/\.[^/.]+$/, "") + '-' + Date.now() + path.extname(file.originalname))
}
})
uploadSingle(fieldName?: string) {
try {
return multer({
storage: this.storage,
limits: { fileSize: 1024 * 1024 * 1 }, // 1MB = 1024 * 1024 * 1
fileFilter: function (req, file, callback) {
const fileTypes = /jpeg|jpg|png/;
const extName = fileTypes.test(path.extname(file.originalname).toLowerCase());
const mimeType = fileTypes.test(file.mimetype);
if (extName && mimeType) {
callback(null, true)
} else {
callback(new Error('Error: Images Only!'), null)
}
}
}).single(fieldName);
} catch (err) {
console.log(err.message)
}
}
}
export default new MediaFiles();

I don't think you could have two multer objects, I was having the same problem and here is what worked for me.
const storage = multer.diskStorage()
const mediaFiles = multer({
storage:storage })
.fields([{ name: 'icon_url', maxCount: 1 }, { name: 'background_url', maxCount: 1 } ]
router.post('/', mediaFiles, async (req, res) => {
console.log(req.files) // req.files is an array of files
}

Related

Upload Image and PDF in rest API using node js with mongoose

I have try to insert some data into mongodb database using node js REST API but I got an error Unexpected field Im new to node please help me. whitePaper is my pdf file If I upload data like title, description and image only it gives the Correct answer with status code 201 but I try to upload all data and pdf but it gives the error
model code:
description: {
type: String,
required: true
},
imgURL: {
type: String,
required: true
},
whitePaperLink: {
type: String,
required: true,
},
app.js file
app.use('/whitePaper', express.static('whitePaper'));
router file
const whitePaperLink = multer.diskStorage({
destination: './whitePaper/',
filename: (req, file, cb) => {
return cb(null, `${file.fieldname}_${Date.now()}${path.extname(file.originalname)}`);
}
});
const whitePaperFilter = (req, file, cb) => {
if (file.mimetype === 'application/pdf') {
cb(null, true)
} else {
cb(null, false)
}
};
const whitePaperUpload = multer({
storage: whitePaperLink,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: whitePaperFilter
});
router.post('/', checkAuth, imageUpload.single('imgURL'), whitePaperUpload.single('whitePaperLink'),
PostController.create_Post)
controller file
exports.create_Post = async (req, res) => {
const post = new Post({
title: req.body.title,
category: req.body.category,
description: req.body.description,
imgURL: req.file.path,
whitePaperLink: req.file.path,
publishDate: req.body.publishDate,
});
try {
const addPost = await post.save()
res.status(201).json({
message: 'Post Added Succesfully.'
})
} catch (error) {
console.log(error);
res.status(500).json({
message: error
})
}
}
If you'll use upload.single for each field it'll give error Unexpected Field.
Multer takes all files at once for execution, and in your case you've 2 different files and it'll take both files to upload.single.
So, instead of upload.single use upload.fields.
In your route.js, do it like this:
const destination = (req, file, cb) => {
switch (file.mimetype) {
case 'image/jpeg':
cb(null, './images/');
break;
case 'image/png':
cb(null, './images/');
break;
case 'application/pdf':
cb(null, './whitePaper/');
break;
default:
cb('invalid file');
break;
}
}
const storage = multer.diskStorage({
destination: destination,
filename: (req, file, cb) => {
return cb(null, `${file.fieldname}_${Date.now()}${path.extname(file.originalname)}`);
}
});
const fileFilter = (req, file, cb) => {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png' || file.mimetype === 'application/pdf') {
cb(null, true)
} else {
cb(null, false)
}
};
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5,
},
fileFilter: fileFilter
});
// add post
router.post('/', upload.fields([{ name: 'imgURL', maxCount: 1 }, { name: 'whitePaperLink', maxCount: 1 }]), PostController.create_Post)
Edit:
You can also do it like this:
const uploadPostData = (req, res, next) => {
upload.fields([{ name: 'imgURL', maxCount: 1 }, { name: 'whitePaperLink', maxCount: 1 }])(req, res, (err) => {
console.log(req.files);
req.body.imgURL = req.files.imgURL[0].path.replace('/\\/g','/');
req.body.whitePaperLink = req.files.whitePaperLink[0].path.replace('/\\/g','/');
next()
})
}
// add post
router.post('/', uploadPostData, PostController.create_Post)

How to loop into multiple fieldname to get the files.path

I have Node.js app, served by express, with my frontend being made with React.js. My issue is i got to different fieldname for my images. Cover Photo and Avatar Photo. I'm having hard time to figure out how to loop into to different fieldname and get the path of the image. The result that i want is the backend will res.send(path of the image either avatar or cover or both of them).
// imageuploadroutes
import express from 'express';
const router = express.Router();
import multer from 'multer';
import path from 'path';
const storage = multer.diskStorage({
destination: function (req, file, cb) {
if (file.fieldname === 'coverPhoto') {
cb(null, 'public/images/cover');
} else {
cb(null, 'public/images/avatar');
}
},
filename: function (req, file, cb) {
cb(
null,
`${file.fieldname}-${Date.now()}${path.extname(file.originalname)}`
);
},
});
const upload = multer({
storage,
limits: {
fileSize: '2mb',
},
fileFilter: (req, file, cb) => {
if (
file.mimetype == 'image/png' ||
file.mimetype == 'image/jpg' ||
file.mimetype == 'image/jpeg'
) {
cb(null, true);
} else {
cb(null, false);
return cb(new Error('Only .png, .jpg and .jpeg format allowed!'));
}
},
});
router.post(
'/user/profile',
upload.fields([
{
name: 'coverPhoto',
maxCount: 1,
},
{
name: 'avatarPhoto',
maxCount: 1,
},
]),
function (req, res) {
var file = req.files[Object.keys(req.files)[0]];
console.log(file)
}
);
export default router;
Result
[
{
fieldname: 'avatarPhoto',
originalname: 'Screen Shot 2021-03-02 at 11.49.56 AM.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'public/images/avatar',
filename: 'avatarPhoto-1614704247624.png',
path: 'public/images/avatar/avatarPhoto-1614704247624.png',
size: 597941
}
]
but the problem is I can't get the .path
The file is an array, you should iterate over it:
var file = req.files[Object.keys(req.files)[0]];
console.log(file);
file.forEach(fileData => {
console.log(fileData.path);
})

Error uploading multiple images in node.js

I am trying to upload images in mongo db but after clicking on send in postman it shows "img": null
I am using flutter for frontend so I want to make a rest api I am able to upload single image but when I am trying to upload multiple images it shows
"img": null
I have also created a schema
where I have set
img:{
type: array,
default:"",
}
const express = require("express");
const router = express.Router();
const Profile = require("../models/profile.model");
const middleware = require("../middleware");
const multer = require("multer");
const path = require("path");
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "./uploads");
},
filename: (req, file, cb) => {
cb(null, req.decoded.username + ".jpg");
},
});
const fileFilter = (req, file, cb) => {
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 * 6,
},
// fileFilter: fileFilter,
});
//adding and update profile image
router
.route("/add/image")
.patch(middleware.checkToken, upload.array("img",5), (req, res) => {
Profile.findOneAndUpdate(
{ username: req.decoded.username },
{
$set: {
img: req.files.path,
},
},
{ new: true },
(err, profile) => {
if (err) return res.status(500).send(err);
const response = {
message: "image added successfully updated",
data: profile,
};
return res.status(200).send(response);
}
);
});
when you upload multiple images, multer create a array of object like this :
req.files : [{…}, {…}, {…}]
that one of the property of objects is path, so there are many way to insert to path in img.
if type of img defined array [] in schema you can do like this in findOneAndUpdate :
{
$set: {
img: req.files.map(file => file.path),
},
}

facing problem while uploading image in node

trying to upload an image using multer and getting this error
ENOENT: no such file or directory, open 'C:\Users\Marwa\mern-stack\uploads\images\74.jpeg'
POST /api/users/signup 500 23.065 ms - 1711
RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: ENOENT
at ServerResponse.writeHead (_http_server.js:248:11)
any ideas why this error happened?
this is the file-upload middleware
and the image should be stored in uploads/images folder
const multer = require("multer");
const MIME_TYPE_MAP = {
"image/png": "png",
"image/jpeg": "jpeg",
"image/jpg": "jpg",
};
const fileUpload = multer({
limits: { fileSize: 2 * 1024 * 1024 },
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "uploads/images");
},
filename: (req, file, cb) => {
const ext = MIME_TYPE_MAP[file.mimetype];
cb(null, Math.floor(Math.random() * 100) + "." + ext);
},
}),
fileFilter: (req, file, cb) => {
const isValid = !!MIME_TYPE_MAP[file.mimetype];
let error = isValid ? null : new Error("Invalid mime type!");
cb(error, isValid);
},
});
module.exports = fileUpload;
then I pass this middleware to route I want to add image for (signup)
router.post(
"/signup",
fileUpload.single("image"),
[
check("name").not().isEmpty(),
check("email").isEmail(),
check("password").isLength({ min: 6 }),
],
createUser
);

upload file in angular 2 with nodejs

I am new in angular 2 and node js.
I need to upload file in folder using anjular2 and also want to store that file name in mongodb database, at server side. For that I tried this but its not working.Using code is that:
app.component.ts:
attachment: any;
hasBaseDropZoneOver: boolean = false;
options: Object = {
url: 'http://localhost:3000/upload'
};
sizeLimit = 2000000;
handleUpload(data): void {
if (data && data.response) {
this.attachment = data;
}
}
fileOverBase(e:any):void {
this.hasBaseDropZoneOver = e;
}
beforeUpload(uploadingFile): void {
console.log(uploadingFile.size + ' -- '+this.sizeLimit);
if (uploadingFile.size > this.sizeLimit) {
uploadingFile.setAbort();
alert('File is too large');
}
}
this is app.html file:-
<input type="file" ngFileSelect [options]="options" (onUpload)="handleUpload($event)" (beforeUpload)="beforeUpload($event)">
app.module.ts
import { Ng2UploaderModule } from 'ng2-uploader';
Server Side Code:
const upload = multer({
dest: 'uploads/',
storage: multer.diskStorage({
filename: (req, file, cb) => {
let ext = path.extname(file.originalname);
cb(null, `${Math.random().toString(36).substring(7)}${ext}`);
}
})
});
app.post('/upload', upload.any(), (req, res) => {
res.json(req.files.map(file => {
let ext = path.extname(file.originalname);
return {
originalName: file.originalname,
filename: file.filename
}
}));
});
It is showing me below error:
XMLHttpRequest cannot load http://localhost:3000/upload. Response to preflight request doesn't pass access

Resources