Why is req.file undefined in my route.post? - node.js

I am trying to send a photo from react to node server.
But i have some problems : req.file is undefined and I don't understand why
This is my react code
const formData: any = new FormData();
formData.append("file", {
uri: image.uri,
type: image.type,
name: "tmpImage",
});
try {
await axios.post(`${BACKEND_URL}/recipes/photo`, {
formData,
header: { "Content-Type": "multipart/form-data" },
});
} catch (error) {
console.error("Error when sending image");
}
and here is my nodejs code
multer conf :
export const storage = multer.diskStorage({
destination: function (req, file, callback) {
console.log("here dest");
callback(null, "uploads");
},
filename: function (req, file, callback) {
console.log("here filename");
callback(null, file.originalname);
},
});
export const upload: any = multer({ storage });
route :
recipesRoutes.post(
"/photo",
upload.single("tmpImage"),
async (req: Request, res: Response) => {
console.log("req files =>", req.files);
console.log("req file =>", req.file);
return res.status(200).send();
}
);
express conf :
app.use(cors());
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
req.file is undefined and I don't understand why.
Thanks for help

I think you need to use the different curly brackets for the data that you are sending
and the headers that you configuring. it must be something like this:
await axios.post(`${BACKEND_URL}/recipes/photo`,
{formData},
{header: { "Content-Type": "multipart/form-data" }},
);
based on this example :
import axios from 'axios';
axios.post('https://httpbin.org/post', {x: 1}, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({data}) => console.log(data));
on this page
GitHub

Related

am not able to upload image from react native to nodejs server even i can upload image from postman,

am using "react-native-image-picker": "^3.2.1", to get images from the library am getting it, but am not able to upload it to nodejs server using multer although I can upload an image from postman it means it should work fine
here is my react native code
this.setState({ uri: response.uri });
const bodyToBe = new FormData({ maxDataSize: 20971520 });
bodyToBe.append('photo', {
type: response.type,
uri: response.uri,
name: response.fileName
})
fetch('http://192.168.10.6:5000/api/open/upload-any-image', {
headers: {
Authorization: `Bearer ${this.props.user.userToken}`,
'Accept': 'multipart/form-data',
'Content-Type': 'multipart/form-data',
},
method: 'POST',
body: bodyToBe
})
.then(response => {
console.log(response, "this is response");
response.json().then(res => console.log(res, "its is")).catch(err => console.log(err, "here you go"));
})
.catch(e => {
console.log(e.toString(), "error")
});
and server-side multer config is
'use strict;
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads');
},
filename: function (req, file, cb) {
cb(null, Date.now() + file.originalname);
}
});
const fileFilter = (req, file, cb) => {
// reject a file
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
return cb(null, true);
} else {
return cb(null, false);
}
};
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 25
},
fileFilter: fileFilter
});
module.exports = upload;
and the express route is
console.log("request =>" ,req.files)
return openService
.uploadImage(req.body, req.files, req.user)
.then((data) => {
res.send(RS.successMessage(data))
})
.catch((err) => next(err));
});
Thanks in advance for helping.

Unable to upload image/video files from react-native to nodejs

I am using expo-image-picker in react-native to pick image/video files and multer in nodejs as middleware to download files in directory /public/upload. When i am uploading file along with other parameters from react-native, multer is unable to detect a file present in req.body and hence not downloading any file.
Here is my react-native code using axios
pickImage = async () => {
try {
let options = {
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 1,
// base64:true
}
let result = await ImagePicker.launchImageLibraryAsync(options)
if (!result.cancelled) {
this.setState({ content: result })
}
} catch (E) {
console.log("error in picking image:", E)
}
}
createFormData = (response) => {
const photo = {
uri: response.uri,
type: response.type,
name: "my-img.jpg",
};
const form = new FormData();
form.append('acivityFile',photo);
return form;
};
handleSubmit = async () => {
if (this.state.content) {
const formData = this.createFormData(this.state.content)
console.log("form data:", formData)
try {
const res = await axios.post('http://393ad751391b.ngrok.io/activities',
{
title: "This is the title",
description: "This is a description",
eventType: "LOST & FOUND",
file: formData
},
{
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
},
)
console.log("res:", res.data);
} catch (err) {
console.log("err in post axios:",err)
}
}
}
Here is my route file handling http requests in server-side
const express = require('express');
const Upload = require('./../utils/multerSetup');
const activityController = require('../Controllers/activityController');
const router = express.Router();
router
.route('/')
.get(activityController.getAllActivities)
.post(
Upload.single('activityFile'),
activityController.addActivity
);
Here is my multerSetup.js file in server-side
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/uploads/');
},
filename: function (req, file, cb) {
const ext = file.mimetype.split('/')[1];
cb(null, file.fieldname + '-' + Date.now() + '.' + ext);
},
});
const upload = multer({ storage });
module.exports = upload;
Here is my activityController.js file in server-side
const Activity = require('./../modals/activityModel');
const User = require('./../modals/user');
exports.getActivity = async (req, res, next) => {
console.log('here');
const activity = await Activity.findById(req.params.id);
res.status(200).json({
status: 'success',
data: {
activity,
},
});
};
exports.addActivity = async (req, res, next) => {
if (req.file) {
let file = {
Ftype: req.file.mimetype.split('/')[0],
name: req.file.filename,
};
req.body.file = file;
}
if (!req.body.location) {
req.body.location = {
coordinates: ['77.206612', '28.524578'],
};
}
if (req.body.votes) {
req.body.votes.diff = req.body.votes.up - req.body.votes.down;
}
req.body.creator = "12345" || "req.userId";
const activity = await Activity.create(req.body);
res.status(201).json({
status: 'success',
data: {
activity,
},
});
};
Also when Content-type:'multipart/form-data, then server console throws Error: Multipart:Boundary not found. When i use Content-type:'application/json', then multer does not work.
I just want to know what is the correct way of uploading files with additional parameters from react-native to nodejs multer. Any suggestions would be a great help!

Getting req.body and req.file as empty when uploading file with axios

Here is the frontend:
let file = this.$refs.file.files[0] //"this" refers to vue
let data = new FormData();
data.append("image", file, file.fileName);
data.append("content", this.content);
data.append("title", this.title);
data.append("action_type", "add_article");
axios
.post("http://localhost:3000/api", data, {
headers: {
// "accept": "application/json",
// "Accept-Language": "en-US,en;q=0.8",
// "Content-Type": `multipart/form-data; boundary=${data._boundary}`,
// "auth": util.getCheckedToken(),
'content-type': 'multipart/form-data'
}
})
.then(response => {
alert("success!", response);
})
.catch(error => {
alert("fail!", error);
});
Some part of backend:
app.use(multer({
storage: multer.diskStorage({
destination: (req, file, cb) => { cb(null, '../static/images'); },
filename: (req, file, cb) => { cb(null, my_random.fileName(file.originalname)); }
}),
fileFilter: (req, file, cb) => { cb(null, "image/png image/jpg image/jpeg".split(' ').includes(file.mimetype)); }
}).single('image'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
See tags for the tools I am using. I get no error message and req.file and req.body are empty. What can be the reason of the problem?
Had a similar problem trying to send a text/csv file, fixed by parsing the content type before the route.
Like this:
app.use(bodyParser.raw({type: multipart/form-data}));
Before
app.use(multer({}))
bodyParser.raw([options]) returns middleware that parses all bodies as a Buffer and only looks at requests where the Content-Type header matches the type option

How to upload images from react native to nodejs?

I'm trying to upload an image with expo picker image to a nodejs server.
The problem is I never receive the image. I tried so many things I'm desesperate :(
Here is my code :
React-Native
postImage = async (image) => {
const photo = {
uri: image.uri,
type: "image/jpg",
name: "photo.jpg",
};
const form = new FormData();
form.append("test", photo);
axios.post(
url,
{
body: form,
headers: {
'Content-Type': 'image/jpeg',
}
}
)
.then((responseData) => {
console.log("Succes "+ responseData)
})
.catch((error) => {
console.log("ERROR " + error)
});
}
pickImage = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
// mediaTypes: ImagePicker.MediaTypeOptions.All,
// allowsEditing: true,
// aspect: [4, 3],
quality: 1
});
if (!result.cancelled) {
try {
await this.postImage(result);
} catch (e) {
console.log(e);
}
this.setState({ image: result.uri });
}
};
It always works.
And here the nodejs code
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const multer = require('multer');
const fs = require("fs");
const app = express();
const upload = multer({
dest: "upload/",
});
// app.use(upload.single("test"));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cors());
app.listen(8080, () => {
console.log("running ...")
})
app.post("/upload", upload.single("photo.jpg"), async (req, res) => {
console.log("body =>", req.body);
console.log('files => ', req.files);
console.log("file =>", req.file);
// const oldpath = req.body.;
// const newpath = '/Users/mperrin/test/test-native/test-upload-photo/server/lol.jpg';
// fs.rename(oldpath, newpath, (err) => {
// if (err) {
// throw err;
// }
// res.write('File uploaded and moved!');
// res.sendStatus(200);
// });
res.sendStatus(200);
});
I always see this in the console and I don't know what to do with that ...
body => {
body: { _parts: [ [Array] ] },
headers: { 'Content-Type': 'image/jpeg' }
}
At the moment only the folder "upload" is created.
I don't know where I can get the files, I guess I'm really missing something but I don't know what.
Thanks for help guys !
I've never used multer before but after a quick review of the docs it looks like you need to have the same name in the headers as you're expecting in the node side post
Right now, in your header you have
name: 'photo.jpg'
and the following in your node post
upload.single("test")
Your post is looking for something with the name 'test' not 'photo.jpg' and you're sending 'photo.jpg'
Try it out and let me know how it goes.
Edit: My mistake, you may have add
name: "test"
to the headers here instead of in the photo object:
axios.post(
url,
{
body: form,
headers: {
'Content-Type': 'image/jpeg',
}
})

Why can not find the server route of an express server from react native when trying to upload a file?

i have configured an express server that use multer as a middleware in order to upload images to GCS, it works as expected and wanted when making the respective request from insomnia, but when trying to do it from my project in react native, i can not even get connected to that route, and actually i do not know the reason and what else to try.
this is the code from the server:
const storage =
multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
cb(null, Date.now() + path.extname(file.originalname))
}
})
const upload = multer({ storage: storage })
app.listen(3000);
app.use(router)
router.post('/uploadImage', upload.single('file'), async function (req, res) {
console.log("se conectaron a /uploadingImage")...
This is code from the frontend in react native:
_pickImage = async () => {
this.getPermissionAsync()
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
});
state = {
search: '',
};
this.uploadImage(`http://192.168.1.69:3000/uploadImage`, {
file: {
height:result.height,
type: result.type,
uri: result.uri,
width: result.width,
}
}).then(r => {
});
if (!result.cancelled) {
this.setState({ image: result.uri });
}
};
async uploadImage(url, data) {
let options = {
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
method: 'POST'
}
options.body = new FormData();
for (let key in data) {
options.body.append(key, data[key]);
}
return fetch(url, options)
.then(async response => {
return response.json()
.then(responseJson => {
return responseJson;
});
});
}
My server have never log in the console the first line in the route ("se conectaron a /uploadingImage")

Resources