I'm pretty new working with angular and nodejs. I'm trying to upload files to the server and it is working fine, but I want to put the files on specific folder because I don't want to have files together. So this is my code:
const storage = multer.diskStorage({
console.log('carId ' + req.body.carId) //here show undefined
destination: function (req, file, cb) {
cb(null, DIR);
},
filename: function (req, file, cb) {
FILENAME = Date.now() + path.extname(file.originalname);
cb(null, FILENAME);
}
})
const _upload = multer({ storage: storage }).single('file');
exports.upload = async (req, res) => {
try {
_upload(req, res, (err) => {
if (err) {
res.status(500).send(error.message);
}
else {
this.create(req, res); //in this method I can get the carId by doing req.body.carId
}
})
} catch (error) {
res.status(500).send(error.message);
}
}
In the code, with comments I marc where I can get the value and where not. The idea is in the funtion storage get the carId and put the file on /uploads/13 (13) is the value on req.body.carId
Here is how I create the data:
const form = new FormData();
for (let i = 0; i < this.fileArray.length; i++) {
form.append('file', this.fileArray[i])
form.append('name', this.fileArray[i].name)
form.append('carId', this.carId)
}
In the service I do this:
uploadFile(data: FormData): Observable<any> {
return this._http.post(`${this.apiUrl}/upload`, data).pipe(catchError(this.handleError));
}
Related
I am trying to upload an image from my front end to the backend but it it doesn't send the image in the request
It says that the formdata is empty and it says that there's no image found, where is the problem and how can I fix this error?
Here is the code from the Frontend made in react:
const [userInfo, setuserInfo] = useState({
file:[],
filepreview:null,
});
const handleInputChange = (event) => {
setuserInfo({
...userInfo,
file:event.target.files[0],
filepreview:URL.createObjectURL(event.target.files[0]),
});
}
const [isSucces, setSuccess] = useState(null);
const submit = async () =>{
const formdata = new FormData();
formdata.append('avatar', userInfo.file);
console.log(formdata)
Axios.post("http://localhost:4000/imageupload", formdata,{
headers: { "Content-Type": "multipart/form-data" }
})
.then(res => { // then print response status
console.warn(res);
if(res.data.success === 1){
setSuccess("Image upload successfully");
}
})
}
The code of the Backend made in NodeJS:
const storage = multer.diskStorage({
destination: path.join(__dirname, './temp', 'uploads'),
filename: function (req, file, cb) {
// null as first argument means no error
cb(null, Date.now() + '-' + file.originalname )
}
})
app.post('/imageupload', async (req, res) => {
try {
// 'avatar' is the name of our file input field in the HTML form
let upload = multer({ storage: storage}).single('avatar');
upload(req, res, function(err) {
// req.file contains information of uploaded file
// req.body contains information of text fields
if (!req.file) {
return res.send('Please select an image to upload');
}
else if (err instanceof multer.MulterError) {
return res.send(err);
}
else if (err) {
return res.send(err);
}
const classifiedsadd = {
image: req.file.filename
};
res.send("ok")
});
}catch (err) {console.log(err)}
})
Edit:
Multer is essentially a nodejs router,i.e. a function that can be pipelined between your HTTP request and HTTP response.
I think that you should first make multer analyze your HTTP content and to actually populate the req.file before actually evaluate express parsers do their job.
const storage = multer.diskStorage({
destination: path.join(__dirname, './temp', 'uploads'),
filename: function (req, file, cb) {
// null as first argument means no error
cb(null, Date.now() + '-' + file.originalname )
}
})
let upload = multer({ storage: storage});
app.post('/imageupload', upload.single('avatar'), async (req, res) => {
try {
// 'avatar' is the name of our file input field in the HTML form
// req.file contains information of uploaded file
// req.body contains information of text fields
if (!req.file) {
return res.send('Please select an image to upload');
}
else if (err instanceof multer.MulterError) {
return res.send(err);
}
else if (err) {
return res.send(err);
}
const classifiedsadd = {
image: req.file.filename
};
res.send("ok")
}catch (err) {console.log(err)}
})
I am assuming that your upload code is working. Have you tried to read the HTTP request from your browser to see that the image has been correctly attached to the request?
Because probably the issue lies in the fact that you are not actually parsing the image.
const file = new File(userInfo.file, "avatar.png", {
type: 'image/png' // choose the appropriate
});
const formdata = new FormData();
formdata.append('avatar', file);
console.log(formdata)
I want to upload files from the form data in react which is being posted by axios like this.
const addNewProduct = () => {
const newProduct = {
name: name,
cost: cost,
size: size,
color: color,
material: material,
discount: discount,
description: description,
category: category
};
const nulls = Object.values(newProduct).filter(p => p === null);
if(nulls.length === 0 && images.imageFiles) {
let productFormData = new FormData();
productFormData.append('productInfo', JSON.stringify(newProduct));
productFormData.append('productImages', images.imageFiles);
const addUrl = "http://localhost:8080/cpnl/addproduct";
axios({
method: "POST",
url: addUrl,
data: productFormData,
headers: { "Content-Type": "multipart/form-data" }
})
.then((response) => {
console.log(response.data.msg);
})
.catch((response) => {
console.error(response);
});
}else {
Notiflix.Notify.Warning("Check your inputs!");
console.log(nulls);
console.log("product: \n" + JSON.stringify(newProduct));
}
};
then I want to upload images with multer to images folder. this is my code:
const storage = multer.diskStorage({
destination: "./public/images",
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
const upload = multer({
storage: storage,
limits:{fileSize: 1000000},
fileFilter: function(req, file, cb){
checkFileType(file, cb);
}
}).array("productImages", 5);
function checkFileType(file, cb) {
// Allowed ext
const filetypes = /jpeg|jpg|png/;
// Check ext
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
// Check mime
const mimetype = filetypes.test(file.mimetype);
if(mimetype && extname){
return cb(null,true);
} else {
cb('Error: Images Only!');
}
}
//receive form data from front-end and add new product to database
router.post('/addproduct', async (req, res) => {
upload(req, res, (err) => {
if(err) {
res.status(400).json({
msg: err
});
} else {
if(req.files == undefined) {
res.status(400).json({
msg: "Error: No file selected! please contact the developer."
});
} else {
data = req.body.productInfo;
res.status(200).json({
msg: "Files uploaded!"
});
console.log( "images: " + req.files);
console.log("data" + data);
}
}
});
});
first problem: I'm getting image files inside req.body.productImages and not inside req.files
second problem: when I send the request node js throws me this error:
TypeError: upload is not a function
why everything is messed up!?
Edit: I restarted the server and now I'm getting data but the files are not being uploaded. no error is shown.
UPDATE: second problem fixed
First Problem : You have used .array("productImages", 5); in your upload function. use .array("files", 5); to get the file in req.files.
Second Problem : I guess there is some typo error in your code upload(req, res, (err)... there is one extra bracket it should be only upload(req,res,err )...
I am creating a React and Node application, and at the moment I need to upload a PDF file, the code works well, but I was wondering how to use front variables to create the file name by multer.
The code...
Front:
const handleSubmit = async (e) => {
const dado = new FormData()
const year = data.split("/")
const dd = year[0];
const mm = year[1];
const aaaa = year[2];
dado.append('file', file)
dado.append('uni', uni)
dado.append('dd', dd)
dado.append('mm', mm)
dado.append('aaaa', aaaa)
console.log(dado)
axios.post("http://localhost:8080/api/comprebem/file", dado, {
})
.then(res => {
console.log(res.statusText)
})
}
Back:
const storage = multer.diskStorage({
destination:"../login/public/comprebem/ibama/",
filename: function (req, file, cb) {
console.log(file);
cb(null, `unidade${"req['uni']"}_data${file.originalname}` )
}
})
const upload = multer({ storage: storage }).single('file')
app.post('/api/comprebem/file',function(req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
return res.status(500).json(err)
} else if (err) {
return res.status(500).json(err)
}
return res.status(200).send(req.file)
})
});
I am giving post request /product/create with some value and an image.
if I console every value before
upload(req, res, (err) => {})
it is showing properly with out image info.
if I receive the value after upload(req, res, (err) => {})
No value is showing.
Full post request code:
app.post('/product/create', (req, res) => {
let filename;
upload(req, res, (err) => {
if(err){
res.render('index', {
msg: err
});
} else {
if(req.file == undefined){
res.render('index', {
msg: 'Error: No File Selected!'
});
} else {
res.render('index', {
msg: 'File Uploaded!',
filename = req.file.filename;
});
}
}
});
const product = {
title : req.body.title,
desc : req.body.desc,
image : filename,
}
});
configuring Multer:
const storage = multer.diskStorage({
destination: './public/uploads/',
filename: function(req, file, cb){
cb(null,file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
const upload = multer({
storage: storage,
limits:{fileSize: 1000000},
fileFilter: function(req, file, cb){
checkFileType(file, cb);
}
}).single('myImage');
function checkFileType(file, cb){
const filetypes = /jpeg|jpg|png|gif/;
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = filetypes.test(file.mimetype);
if(mimetype && extname){
return cb(null,true);
} else {
cb('Error: Images Only!');
}
}
Multer does not support 'req.file.filename' outside upload function. As filename, originalname, fieldname etc is inbuild API of multer. It is limited to upload function only.
Now, if you are trying to upload product values inside database then you have to create an insert function inside multer upload function only.
i want to upload the file into a folder which should be get from form data submit by user. which is req.body.coursename
/*conditions for directory check*/
var isvalidate = function (data) {
var data = data;
var dir = '../uploads'+'/'+data;
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
return dir;
} else {
return dir;
}
};
/*multer*/
var date = moment().format('YYYY-MM-DD');
var storage = multer.diskStorage ({
destination: function (req, file, callback) {
console.log("filename upload",file.originalname);
callback(null, isvalidate(req.body.coursename));
},
filename: function (req, file, callback) {
//console.log("filename upload",file.originalname);
callback(null, date+ '-' +file.originalname );
}
});
var data = multer({ storage : storage }).any();
/*file upload*/
router.post('/create',function(req, res) {
console.log(req.body);
data(req, res, function(err) {
console.log(req.body);
//isvalidate (req.body.coursename);
if (err) {
res.json({error_code:1,err_desc:err});
return;
}
});
});
How can I create a folder with the name req.body.coursename for file upload?
You can't but you can move the file to other locations after the file is uploaded. You could make your storage object a module and change the directory dynamically via init
var multer = require('multer'); // middleware for handling multipart/form-data,
// Constructor
module.exports = function (name) {
try {
// Configuring appropriate storage
var storage = multer.diskStorage({
// Absolute path
destination: function (req, file, callback) {
callback(null, './uploads/'+name);
},
// Match the field name in the request body
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
return storage;
} catch (ex) {
console.log("Error :\n"+ex);
}
}
OR Use busboy
var Busboy = require('busboy');
var fs = require('fs');
app.post('.....',fucntion(req, res, next){
var busboy = new Busboy({ headers: req.headers });
busboy.on('field', function(fieldname, val) {
req.body[fieldname] = val;
});
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
fstream = fs.createWriteStream("path/desiredImageName");
file.pipe(fstream);
fstream.on('close', function() {
file.resume();
});
})
return req.pipe(busboy);
})
OR you can use changedest
app.post('/api/:type', multer({
dest: './uploads/',
changeDest: function(dest, req, res) {
var newDestination = dest + req.params.type;
var stat = null;
try {
stat = fs.statSync(newDestination);
} catch (err) {
fs.mkdirSync(newDestination);
}
if (stat && !stat.isDirectory()) {
throw new Error('Directory cannot be created because an inode of a different type exists at "' + dest + '"');
}
return newDestination
}
}), function(req, res) {
//set your response
});