React Native && Node js How to upload image - node.js

I am having trouble uploading an image from my react native app. I have a react app that uploads images to the backend from camera as a file.
let pic = await camera.current.takePictureAsync({
quality: 1,
base64: true,
});
setPicture(pic);
Then
onPress={() => {
const formData = new FormData();
formData.append("file", {
name: picture + "",
type: picture.type,
uri:
Platform.OS === "ios"
? picture.uri.replace("file://", "")
: picture.uri,
});
console.log(formData);
httpClient
.post("demo/testsaveimg", formData)
.then((request) => {
if (request.data == "ok") {
console.log(request.data);
}
});
}}
This is my Formdata to service
and then, here is my service
app.post('/testsaveimg', async function (req, res, next) {
let storageUploadFile = multer.diskStorage({
destination: (req, file, next) => {
const folder = './test/'
if (!fs.existsSync(folder)) {
fs.mkdirSync(folder)
}
next(null, folder)
},
filename: (req, file, next) => {
const ext = file.mimetype.slice("/")[1]
next(null, `${file.fieldname}-${Date.now()}.${ext}`)
}
})
let UploadFile = multer({ storage: storageUploadFile }).single("files");
UploadFile(req, res, async function (err) {
console.log(req.file);
if (err instanceof multer.MulterError) {
return res.status(500).json(err);
} else if (err) {
console.log(99);
return res.status(500).json(err);
}
if (req.file != undefined) {
console.log("ok");
res.json("ok")
} else {
console.log("no");
res.json("no")
}
})
})
But there are no pictures in the folder "./test/" and response is "no"
that means "req.file = undefined"
What steps am I doing wrong?
or is there another way to write?

Related

"Cannot read properties of undefined (reading '0')

I am making a guide's update controller which include name, email, password, avatar[image] and guidelicence[pdf]. It gives the error cannot read undefined at(0) but the same logic runs for signup. I am using multer and cloudinary for form data, and have been stuck for 2 days.
Update Route
routes.put(
"/:userID",
upload.fields([
{ name: "avatar", maxCount: 1 },
{ name: "guidelicense", maxCount: 1 },
]),
update
);
Update Controller
exports.update = async (req, res) => {
try {
// handle the form data
const {
fullname,
password,
email,
address,
isAvalaible,
phonenumber,
cnic,
} = req.body;
// handle the image file
const avatar = req.files.avatar[0];
console.log(req.files.avatar[0]);
// handle the PDF file
const guideLicense = req.files.guidelicense[0];
console.log(req.files.guidelicense[0]);
// upload the image to Cloudinary
cloudinary.uploader.upload(
avatar.path,
{ resource_type: "image" },
(err, image) => {
if (err) throw err;
// store the image URL in the database
const avatarUrl = image.url;
// upload the PDF to Cloudinary
cloudinary.uploader.upload(
guideLicense.path,
{ resource_type: "raw" },
(err, file) => {
if (err) throw err;
// store the PDF URL in the database
const guideLicenseUrl = file.url;
// update the guide's information in the database
Guides.findOneAndUpdate(
{ email },
{
fullname,
password,
avatarUrl,
guideLicenseUrl,
address,
isAvalaible,
phonenumber,
cnic,
},
(err, guide) => {
if (err) throw err;
res.status(200).json({ message: "Guide updated successfully" });
}
);
}
);
}
);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
multer configuration
if (!fs.existsSync("./uploads")) {
fs.mkdirSync("./uploads");
}
// Multer config
module.exports = multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./uploads");
},
filename: function (req, file, cb) {
cb(null, file.originalname);
},
}),
limits: { fileSize: 1024 * 1024 * 5 },
fileFilter: (req, file, cb) => {
let ext = path.extname(file.originalname);
if (ext !== ".jpg" && ext !== ".jpeg" && ext !== ".png" && ext !== ".pdf") {
cb(new Error("File type is not supported"), false);
return;
}
cb(null, true);
},
});
i wanted to get guide updated successfully but got
{
"message": "Cannot read properties of undefined (reading '0')"
}
error
You need to parse the req before accessing it.
Use the parsed "request" to access the data.
const request = JSON.parse(req);

Upload file using mutler without disabling bodyparser in NEXTJS

I am trying to upload an image file using mutler along with some form data. Every solution I've looked suggests to disable the bodyparser but if I disable the body parser then I cannot parse the request body.
Backend POST api along with function that runs middleware:
case 'POST':
if (req.body instanceof FormData) {
await runMiddleware(req, res, upload.single('image'))
}
console.log('ID: ',req.query.id)
Courses.findByIdAndUpdate(req.query.id, req.body, {new: true}, (err, result) => {
if(err)
{
console.log('Error in findByIdAndUpdate: ',err)
res.status(400).json({ success: false, data: result })
}
else {
console.log('Success in findByIdAndUpdate: ',result)
res.status(200).json({ success: true, data: result })
}
})
below is the function
function runMiddleware(req, res, fn) {
return new Promise((resolve, reject) => {
fn(req, res, (result) => {
if (result instanceof Error) {
return reject(result)
}
return resolve(result)
})
})
}
Upload Middleware
import multer from "multer";
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "public/uploads");
},
filename: (req, file, cb) => {
cb(null, "upload" + Date.now() + "-" + file.originalname)
}
})
module.exports = multer({storage})
Front-End API call
const createUpdateFormData = () => {
const data = {
title: getValues('title'),
categories: getValues('categories'),
description: getValues('description'),
image: (getValues('file') ? getValues('file')[0] : null),
}
let formData;
if (data.image) {
formData = new FormData();
Object.entries(data).forEach(([key, value]) => {
if(value)
formData.append(key, value);
});
}else {
formData = {}
Object.entries(data).forEach(([key, value]) => {
if(value)
formData[key] = value;
});
}
return formData
}
const handleUpdateRequest = (id,formData) => {
console.log(formData)
const updateReq = axios.post(`/api/courses/${id}`, formData)
toast.promise(updateReq, {
loading: "Processing...",
error: (err) => {
console.log(err)
if (err.response.status === 409)
return 'Course already exists!'
else
return 'Oops something went wrong!'
},
success: (res) => {
console.log(res)
const newState = courseState.map(course => course._id === id ? res.data.data : course)
setCourses(newState)
// console.log('NewState: ', courseState)
return "Course updated successfully!"
}
});
}
I am using the useForm hook

Saving Images React To Nodejs

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)

uploading files from react to node js with multer

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 )...

multer req file is undefined but why?

Can anyone tell me why my req.file is undefined?
I add the content header type,
I add single.photo but I get no data
frontend:
## data is equal to this:
Object {
"filename": "3ccc61e1-3c49-4538-9594-b4987b3fa66f.jpg",
"type": "image/jpg",
"uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/UNVERIFIED-xxxxx-test/ImagePicker/3ccc61e1-3c49-4538-9594-b4987b3fa66f.jpg",
}
const uploadStory = async data => {
try {
const form = new FormData();
form.append('photo', data);
const options = {
headers: {
'Content-Type':'multipart/form-data',
'Accept':'application/json'
},
method: 'POST',
body: form
};
const res = await fetch('http://xxxxxxx.xx:3000/createstory', options);
const out = await res.json();
return out;
} catch(e) {
console.log(e);
return e;
}
};
export default uploadStory;
backend:
const multer = require('multer');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, 'uploads/')
},
filename: function(req, file, cb) {
console.log(req);
cb(null, `${file.filename}-${Date.now()}`)
}
});
const upload = multer({
storage: storage
}).single('photo');
module.exports = async (req, res, next) => {
upload(req, res, function(err) {
if(err) {
console.log(err)
return;
} else if (err instanceof multer.MulterError) {
console.log(err);
} else {
console.log(req.file);
console.log('hi')
}
});
};
..................................
..................................
..................................
..................................
Make sure your data object looks like this
{
name: "3ccc61e1-3c49-4538-9594-b4987b3fa66f.jpg",
type: "image/jpg",
uri: "file:///data/user/0/host.exp.exponent/cache/ExperienceData/UNVERIFIED-xxxxx-test/ImagePicker/3ccc61e1-3c49-4538-9594-b4987b3fa66f.jpg",
}
In your data Object your key is filename instead of name
Change your upload to this
const upload = multer({
storage: storage,
});
And then,
module.exports = upload.single('photo'), async (req, res) => {
try {
console.log(req.body); // Body Here
console.log(req.file); // File Here
res.status(500).send('Fetch Completed Successfully');
} catch (error) {
console.log(error);
res.status(500).send('Error');
}
}

Resources