React Native Axios cannot upload files to server FormData - node.js

Im implementing a function to upload titles, descriptions, and images to the server. Here is my snippet of Front-end code:
const [imageFiles, setImageFiles] = React.useState([]);
const callApi = async () => {
const formData = new FormData();
formData.append('title', 'test');
formData.append('content', 'tesst1');
imageFiles.forEach(imageFile => {
formData.append('files', imageFile);
});
const response = await axios({
method: 'post',
url: 'http://localhost:8080/api/complain',
headers: {
'Content-Type': 'multipart/form-data; ',
Authorization:
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
},
data: formData,
});
};
const openCamera = () => {
let imgList = [];
ImagePicker.openPicker({
multiple: true,
waitAnimationEnd: false,
includeExif: true,
compressImageQuality: 0.8,
maxFiles: 5,
includeBase64: true,
})
.then(images => {
images.map(image => {
imgList.push({
filename: image.filename,
path: image.path,
data: image.data,
type: image.mime,
height: image.height,
width: image.width,
});
});
setImageFiles(imgList);
})
.catch(err => {
console.log(err);
});
};
Here is the Back end code:
router.post(
"/complain",
authenticateToken,
upload.array("files"),
complainController.createComplain
);
However, when I console log req.files, it returns an empty array. I have tried different methods such as add transform request, using fetch from react native,... but none of them works. Please help me with this issue. Thank you guys.

Related

can't receive file with multer (node.js-nuxt3)

I use nuxt3/node.js with multer ,
i can't store or receive file in my server and i can't see req.file in root, its empty all time.
server Code:
const upload = multer({ dest: './uploads/' })
router.post('/sendNewQuestionCSV', upload.single('csv'),adminControler.sendNewQuestionCSV.bind(adminControler))
and my FrontEnd Code with nuxt3:
async function fileSelected(e) {
let formData = new FormData();
formData.append("csv", e.target.files[0]);
const res = await $postFetch("/admin/sendNewQuestionCSV", formData, {
"Content-Type": "multipart/form-data",
});
}
note:$postFetch is an method i made my self use fetch and third argument is "headers". its a nuxt3 Plugin
this Plugin code:
export default defineNuxtPlugin(async () => {
return {
provide: {
postFetch: async (url, body,headers={}) => {
let token = useCookie('token');
return await $fetch(url, {
method: 'post',
body: { token: token.value, ...body },
baseURL: useRuntimeConfig().API_BASE,
...headers
}).catch((error) => error.data)
}
}
}
})
try using .append to add the token:
postFetch: async (url, body,headers={}) => {
let token = useCookie('token');
body.append('token', token.value);
return await $fetch(url, {
method: 'post',
body: body,
baseURL: useRuntimeConfig().API_BASE
}).catch((error) => error.data)
}
EDIT
also try removing headers

Not able to POST image files to server

I'm trying to send an image to server using POST request but on server side I'm receiving and empty object.
// Client Side
function uploadFile(thumbnailRef) {
const thumbnail = thumbnailRef.current.files[0];
const formData = new FormData();
formData.append('file', thumbnail)
fetch('http://localhost:8080/upload', {
method: 'POST',
body: formData,
headers: {
'Content-Type': 'multipart/form-data'
},
}).then(res => { console.log(res) })
.catch(err => console.log(err))
}
// server side
app.post('/upload', (req, res) => {
console.log(req.body) // getting empty - {}
res.end()
})
I think it should work if you remove headers. Like this:
function uploadFile(thumbnailRef) {
const thumbnail = thumbnailRef.current.files[0];
const formData = new FormData();
formData.append('file', thumbnail)
fetch('http://localhost:8080/upload', {
method: 'POST',
body: formData,
}).then(res => { console.log(res) })
.catch(err => console.log(err))
}

Image uploads in react native not reaching server

I am sending images to a nodeJs server using react native. I have noticed that when i make the request, there is an image file in the request but the response fails saying photos are needed for file upload. The request however works perfectly on postman.
Here is a sample of the code. I am using react native image crop picker to select the image.
const choosePhotoFromLibrary = () => {
ImagePicker.openPicker({
width: 300,
height: 400,
cropping: true,
// multiple: true,
multiple: false,
mediaType: 'photo'
}).then((image) => {
setPhotos(image.path)
}).catch(err => {
console.log(err);
})
}
getStoreId()
const createProduct = async () => {
console.log(typeof photos);
const data = new FormData()
data.append('name', productName)
data.append('description', description)
data.append('price', price)
data.append('category', productCategory)
data.append('sub-category', productSubCategory)
data.append('condition', productCondition)
data.append('photos', photos)
data.append('type', `Women's wear`)
console.log(data);
var config = {
method: 'post',
url:url,
headers: {
'token': token,
'Content-Type': 'multipart/form-data'
},
data: data
};
try {
const product = await axios(config)
console.log(product);
} catch (err) {
console.log(err.response);
}
Instead of
data.append('photos', photos)
write like this
data.append('photos', {
name: "Example.jpg",
uri: photos, // This should be something like 'file://...'
type: "image/jpg" // MIME type of file
})

NodeJS Axios request returning an odd string

I'm sending a GET request to a third party API and it is returning a odd string (supposed to be an image).
axios.get(`${URL}/test`, {
headers: {
'Content-Type': 'application/json',
},
auth: {
username: USERNAME,
password: PASSWORD
},
responseType: 'blob'
})
.then(async (response) => {
console.log(response.data)
return res.json(response.data);
})
.catch((err) => {
console.log(err);
return res.json("ERROR");
});
The response is:
"����\u0000\u0010JFIF\u0000\u0001\u0001\u0000\u0000\u0001\u0000\u0001\u0000\u0000��\u0000C
How can I convert it to an image or image/url?
Thanks
You can try this
const Fs = require('fs')
const Path = require('path')
const Axios = require('axios')
async function downloadImage () {
const url = 'https://unsplash.com/photos/AaEQmoufHLk/download?force=true'
const path = Path.resolve(__dirname, 'images', 'code.jpg')
const writer = Fs.createWriteStream(path)
const response = await Axios({
url,
method: 'GET',
responseType: 'stream'
})
response.data.pipe(writer)
return new Promise((resolve, reject) => {
writer.on('finish', () => { /* Add your code here */ resolve(); })
writer.on('error', () => { /* Add your code here */ reject(); })
})
}
downloadImage()

Uploading blob/file in react-native, contents is empty

I am able to succesfully upload a blob with proper contents from my web browser, but when I do it from react-native, the upload file is empty. Here is the code:
async function doit() {
const data = new FormData();
data.append('str', 'strvalue');
data.append(
'f',
new File(['foo'], 'foo.txt', {type: 'text/plain'}),
);
await fetch('http://localhost:3002/upload', {
method: 'POST',
body: data
});
}
However doing this same code from react-native, it uploads, but the file is empty.
Here is the node.js server I am using to test this. Loading http://localhost:3002 gives you a button called "upload it". Clicking it does the upload from the web. Screenshots of results are below.
var multiparty = require('multiparty');
var http = require('http');
http
.createServer(function (req, res) {
if (req.url === '/upload' && req.method === 'POST') {
console.log('multipart here');
var form = new multiparty.Form();
form.parse(req, function (err, fields, files) {
console.log(require('util').inspect({ fields, files }, false, null, true));
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ bar: true }));
});
return;
}
console.log('here');
// show a file upload form
res.writeHead(200, { 'content-type': 'text/html' });
res.end(
`
<script>
async function doit() {
const data = new FormData();
data.append('str', 'strvalue');
data.append(
'f',
// new File([new Blob(['asdf'], {type : 'text/plain'})], 'filename.txt'),
new File(['foo', 'what', 'the', 'hell'], 'foo.txt', {type: 'text/plain'}),
);
const res = await fetch('http://localhost:3002/upload', {
method: 'POST',
body: data
});
console.log(JSON.stringify(res, null, 4));
}
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('b').addEventListener('click', doit, false)
}, false);
</script>
<button type="button" id="b">upload it</button>
`
);
})
.listen(3002);
From web browser we see the node server logs this, notice file size is 14.
However from react-native we see file size is 0:
I faced the same problem recently while posting an image from a react-native app to a server. However, I was able to make it work by appending the name and type of the file to the formData instance.
Here, the uri argument to uploadImageAsync is passed as a route parameter from the previous screen.
const postShoutHandler = async () => {
setShoutUploadStatus("Started Upload");
const response = await uploadImageAsync(route.params.captures);
const uploadResult = await response.json();
if (uploadResult === "Upload successful") {
setShoutUploadStatus("Success");
navigation.navigate("Home");
} else {
setShoutUploadStatus("Failed");
}
};
/* <--Upload image function --> */
const uploadImageAsync = (uri: string) => {
const apiUrl = "https://www.yourserver.com/image";
let uriParts = uri.split(".");
let fileType = uriParts[uriParts.length - 1];
let formData = new FormData();
formData.append("img", {
uri,
name: `photo.${fileType}`,
type: `image/${fileType}`,
});
formData.append("description", "HEY");
let options = {
method: "POST",
body: formData,
headers: {
Accept: "application/json",
"Content-Type": "multipart/form-data",
Authorization: "Bearer " + accessToken,
},
};
return fetch(apiUrl, options);
};
/* <--Upload image function --> */
Here is the Image configuration.
const photoData = await camera.takePictureAsync({
base64: true,
exif: false,
});

Resources