how to upload a image file in node.js? - node.js

var title="this is title";
var content="this is content";
const config = { headers: {'Accept': 'application/json', 'Content-Type': 'multipart/form-data' } };
const form = new FormData()
let file =event.target.files[0]
form.append('file', file)
form.append('title', title)
form.append('content', content)`enter code here`
Axios.post("http://localhost:3001/article/get/123", form,config ).then((res)=>{
console.log(res.data)
})

in node I have used multer for upload image or anything.
Below is the code for upload which I have used as a middleware.
const util = require("util");
const path = require("path");
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./Uploads") // folder path where to upload
},
filename: function (req, file, cb) {
cb(null, file.originalname + "-" + Date.now() + path.extname(file.originalname))
}
});
const maxSize = 1 * 20000 * 20000; // file size validation
const uploadFiles = multer({ storage: storage, limits: { fileSize: maxSize } }).array("myfiles", 10); // key name should be myfiles in postman while upload
const uploadFilesMiddleware = util.promisify(uploadFiles);
module.exports = uploadFilesMiddleware;
Below is the function which I have created in controller for upload and file check.
fileUpload = async (req, res) => {
try {
let userCode = req.headers.user_code;
await upload(req, res);
if (req.files.length <= 0) {
return res.status(httpStatusCode.OK).send(responseGenerators({}, httpStatusCode.OK, 'Kindly select a file to upload..!!', true));
}
let response = [];
for (const element of req.files) {
let data = await service.addFileData(element, userCode);
response.push(data); // for file path to be stored in database
}
if (response && response.length > 0) {
return res.status(httpStatusCode.OK).send(responseGenerators(response, httpStatusCode.OK, 'File uploaded sucessfully..!!', false));
} else {
return res.status(httpStatusCode.OK).send(responseGenerators({}, httpStatusCode.OK, 'Failed to upload file kindly try later..!!', true));
}
} catch (error) {
logger.warn(`Error while fetch post data. Error: %j %s`, error, error)
return res.status(httpStatusCode.INTERNAL_SERVER_ERROR).send(responseGenerators({}, httpStatusCode.INTERNAL_SERVER_ERROR, 'Error while uploading file data', true))
}
}
and the route will go like this.
router.post('/upload/file', fileUploadController.fileUpload);
And be sure to keep same name in postman while file upload as in middleware.

The above code is in react.js. I want to do same work in node.js and the file will be upload from the public folder. main issue is how to upload image file in format like we have in frontend event.target.files[0]

Related

Multer is not sending error response back when the mimetype is not matched

Here I tried to build an utility function that receives sub folder path, an array of allowed mimetypes, maximum size of the file and the default error message for mimetype. But I am facing a problem when I am trying to upload a file with different mimetype like pdf or something, I can saw the error on the console but it's not sending as a response. But it's sending the response when file is larger than the allowed maximum size of the function.
const path = require('path');
const multer = require('multer');
const createError = require('http-errors');
function uploader(sub_folder, mimetype, max_size, error_msg) {
const upload_path = path.join(__dirname, `../Public/uploads/${sub_folder}`);
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, upload_path);
},
filename: (req, file, cb) => {
const extName = path.extname(file.originalname);
const file_name = file.originalname.toLowerCase().replace(extName, "").split(" ").join("-") + "-" + Date.now() + extName;
cb(null, file_name);
}
});
const upload = multer({
storage: storage,
limits: {
fileSize: max_size,
},
fileFilter: (req, file, cb) => {
if (mimetype.includes(file.mimetype)) {
cb(null, true);
} else {
cb(createError(error_msg));
}
}
});
return upload;
}
module.exports = {
uploader,
}
Here is I called the my uploader utility function and got the multer upload object.
const multer = require('multer');
const {uploader} = require('../../Uitilies/singUpload');
const avatarUploads = (req,res,next) => {
const upload = uploader(
"avater",
["image/png", "image/jpg", "image/jpeg"],
10000000,
"Only .jpg/.jpeg/.png file with 1MB size is allowed"
);
upload.any()(req,res, (err => {
if(err){
console.log(err.message);
res.status(500).json({
errors: {
avatar: {
msg: err.message,
}
}
});
}else{
next();
}
}));
}
module.exports = avatarUploads;
Here I tried to handle the multer error manually. Because I want to handle it myself.
Here I printed the err.message. The message always print on the console but when it's error of a mimetype then the response didn't send. I have also seen that when the err instanceof multer.MulterError is true then the response is sent but when it's false the response did not send.
my router is,
router.post('/', avatarUploads, adduserValidators, adduserValidatorsHandler, addUser);
Any Solution ?????

How to use Multer middleware to upload array of images

Im trying to use Multer to upload an array of images. At the client side i have a FormData called pictures.
pictures array, from react-native-image-picker:
const [pictures, setPictures] = useState([]);
const imagePickerCallBack = data => {
const picturesData = [...pictures];
const index = picturesData.length;
const image = {
image: data.uri,
fileName: data.fileName,
type: data.type,
index: index,
};
picturesData.push(image);
setPictures(picturesData);
setLoad(false);
};
Step 1 - Create formData with all images:
const data = new FormData();
pictures.forEach(pic => {
data.append('pictures', {
fileName: pic.fileName,
uri: pic.image,
type: pic.type,
});
});
const headers = {
'Content-Type': 'multipart/form-data',
'x-access-token': token,
};
const diaryUpdatePost = await post(`diary/uploadPictures/${diary}`, body, {
headers,
});
Step 2 - Get the request at server side. Im setting up multer and routers:
const router = express.Router();
const multer = require('multer');
const storage = multer.diskStorage({
destination(req, file, cb) {
cb(null, 'uploads/');
},
filename(req, file, cb) {
cb(null, `${file.fieldname}-${Date.now()}`);
},
});
const upload = multer({ storage, limits: { fieldSize: 25 * 1024 * 1024 } });
// Multer with the same FormData (client)
router.post('/uploadPictures/:name', upload.array('pictures'), diaryController.uploadDiaryPictures);
And finally my diaryController, where i need to get all files:
exports.uploadDiaryPictures = async (req, res) => {
// Logging []. I cant access files from here
console.log(`files ${req.files}...`);
};
I already tried to use express-fileupload, but req.files return undefined. Some ideia to help? Thx.
You need to give a count of files you expect to upload:
upload.array('pictures', <number_of_pictures>)
Or if it is allowed to be any number:
upload.any('pictures')
You should also add the file itself to your form data
data.append('pictures', {
name: pic.fileName,
file: pic.image,
type: pic.type,
});
None of the answers here helped. The solution for me was to iteratively append EACH file object from the files array to the same field name given in Multer, instead of appending the files array itself to the field name given in Multer.
So from this:
export const addFiles= createAsyncThunk(
"addFiles",
async (payload: any, thunkApi) => {
const formData = new FormData();
// Here was the problem -- I was appending the array itself
// to the "files" field
formData.append("files", payload.files);
formData.append("data", JSON.stringify(payload?.data || {}));
const response = await axios.post('/user/products/files', formData);
if(response){
return response;
}
return thunkApi.rejectWithValue("");
}
);
I did this:
export const addFiles= createAsyncThunk(
"addFiles",
async (payload: any, thunkApi) => {
const formData = new FormData();
// The following loop was the solution
for (const file of payload.files) {
formData.append("files", file);
}
formData.append("data", JSON.stringify(payload?.data || {}));
const response = await axios.post('/user/products/files', formData);
if(response){
return response;
}
return thunkApi.rejectWithValue("");
}
);
This was my Multer configuration:
multer({ dest: "/uploads" }).array("files")
The files posted to my endpoint were then available to me at:
req.files
PS: Although the accepted answer kind of did that, he did not mention that you cannot append the entire array at once, which was the main problem for me.

How to resize Image on upload using `Multer and Sharp` on Node and Express

I tried to resize my image when it's being uploaded, but I am not succeeding. I am using Node, Expressjs, Mongoose, Multer and Sharp. How do I resize it on upload with Sharp.
Here is my create routes
router.post('/create', upload.single('cover'), async (req, res, next) => {
const fileName = req.file != null ? req.file.filename : null
let witdth = 100;
let height = 100;
sharp(req.file)
.resize(witdth, height).toFile(req.file.path)
const event = new Event({
startingDate: req.body.startingDate,
closingDate: req.body.closingDate,
title: req.body.title,
description: req.body.description,
eventImage: fileName
})
try {
const events = await event.save()
res.redirect("/events")
} catch {
if (event.eventImage != null) {
removeeventImage(event.eventImage)
}
res.render("events/new")
}
});
and my uploader path
const uploadPath = path.join('public', Event.eventImageBasePath)
const imageMineTypes = ['image/jpeg', 'image/png', 'image/gif']
const upload = multer({
dest: uploadPath,
fileFilter: (req, file, callback) => {
callback(null, imageMineTypes.includes(file.mimetype) )
}
})
and this is the error that it's giving
(node:7447) UnhandledPromiseRejectionWarning: Error: Input file is
missing
What am I doing wrong here?
If you specify dest option in multer() it will save the file to that directory and you will have to pass that directory to sharp() like this
sharp(req.file.path)
Otherwise you can drop the dest option and pass the buffer to sharp()
sharp(req.file.buffer)
...
multer({
fileFilter: (req, file, callback) => {
callback(null, imageMineTypes.includes(file.mimetype) )
}

Problem to change request from get to post and change destination of upload file dynamic in multer nodejs

Hey i work with multer package in node js to upload file.
I make it dynamic but the request is in get and i have problem to change it to post.
Its only work to me in get request.
What it doing now?
It save the file in new folder that call flow and take the id from the client.
I need to replace it to post and get the id in post but i want to move the logic to the route and make it stay same. thanks
My Code:
fileupload service:
const path = require("path");
const multer = require("multer");
const crypto = require("crypto");
const models = require("../models");
const fsex = require("fs-extra");
const today = new Date();
const date =
today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate();
const storage = multer.diskStorage({
destination: (req, file, callback) => {
let flowID = req.params.flowID;
let path = `./uploads/flow/${flowID}`;
fsex.mkdirsSync(path);
callback(null, path);
},
filename: (req, file, cb) => {
crypto.pseudoRandomBytes(8, (err, raw) => {
if (err) return cb(err);
cb(
null,
date + "_" + raw.toString("hex") + "_" + path.extname(file.originalname)
);
});
}
});
const upload = multer({ storage: storage }).single("upload");
module.exports = {
upload: upload,
};
my route:
router.get("/uploadfile/:flowID", upload, (req, res, next) => {
const file = req.file;
const flowID = req.params.flowID;
if (!file) {
const error = new Error("Please upload a file");
error.httpStatusCode = 400;
return next(error);
} else {
createFileInDB(file.originalname, flowID, file.filename)
.then(() => {
console.log("File Created");
res.json(file);
})
.catch(err => {
res.status(500).send(err);
});
}
});

Express Multer validate fields before upload

I have been seen this : NodeJS Multer validate fields before upload but is not work. i tried for make validate field before upload in a days and the result is not working. is it because mutler can't do this?
Iam using MERN : MongoDB,React,Express,Node
i want validate this data in Form-data : dataMurid before uploading the image.
is there another way to overcome this? Maybe using other library? and please give me exampale code.
Route
// #route buat edit/create murid baru
router.post('/datasiswa/create',(req, res,next) => {
upload(req,res,(err)=>{
let request = JSON.parse(req.body.newMurid);
// upload(req.body.data.data, res, (err) => {
// console.log(req.body.data.data);
// });
const { errors, isValid } = validateMuridInput(request);
// Check validation
if (!isValid) {
return res.status(400).json(errors);
}
const muridFields = {};
if (request.tempatLahir) muridFields.tempatLahir = request.tempatLahir;
if (request.jenisKelamin) muridFields.jenisKelamin = request.jenisKelamin;
if (request.nis) muridFields.nis = request.nis;
if (request.nama) muridFields.nama = request.nama;
if (request.tanggalLahir) muridFields.tanggalLahir = request.tanggalLahir;
if (request.namaAyah) muridFields.namaAyah = request.namaAyah;
if (request.namaIbu) muridFields.namaIbu = request.namaIbu;
if (request.noTelepon) muridFields.noTelepon = request.noTelepon;
if (request.hpSiswa) muridFields.hpSiswa = request.hpSiswa;
if (request.hpIbu) muridFields.hpIbu = request.hpIbu;
if (request.hpAyah) muridFields.hpAyah = request.hpAyah;
if (request.alamat) muridFields.alamat = request.alamat;
Murid.findOne({ nis: request.nis })
.then((murid) => {
if (murid) {
errors.nis = 'NIS ini sudah terdaftar';
return res.status(400).json(errors);
} else {
const newMurid = new Murid(muridFields);
newMurid.save()
.then((murid) => {
res.json(murid);
})
.catch((err) => {
console.log(err);
});
}
})
});
});
Upload func
const multer = require('multer');
const path = require('path');
// UPLOAD IMAGE
// Set Storage engine
const storage = multer.diskStorage({
destination: './public/uploads/',
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
// Init upload
let upload = multer({
storage: storage,
limits:{fileSize:1000000}, //file size dalam bit
}).fields([{ name: 'fotoDisplay' }, { name: 'newMurid' }]);
With multer, in your req.file, you have all the fields about the file.
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
import fs from 'fs-extra'
router.post('/register', upload.single('avatar'), (req, res, next) => {
return fs.readFile(req.file.path)
.then(content => {
// The content of the file
})
}
req.file has the mimetype and so much more that you can check

Resources