Can't upload file with Multer, React Native and Axios - node.js

I know there are thousands of questions like this, but none of the solutions works for me:
Change to Fetch Api
Use format {uri: ..., type: ..., name: ...} in formData
I also have noticed that I can't send the formData directly in the "data" axios's property (when using Axios({...})), because the formData object has a property call "._parts", so I have to do:
let formData = new FormData()
formData('image', {uri: imagePicker.uri, name: 'some_name.jpeg', type: 'image/jpeg'})
formData('data', {name: 'Andrea'})
let xmlHttp = await Axios({
method: 'POST',
url: `url...`,
data: formData._parts,
headers: {
Authorization: `Bearer ${_token}`,
'Content-Type': 'multipart/form-data',
},
} ).catch(error => {
throw error
});
Then, in Node, I get this:
req.body -> [Object: null prototype] {}
req.file -> undefined
upload.single("image"), in router.post and multerS3.
Some idea? Thank you

I had the same problem with Axios for 6 days :D , there is no problem with Multer i got.
but in the code you leave data should be formData not the formData._parts.
just check it if it doesnt solve your problem i strongly recommend you to use https://github.com/joltup/rn-fetch-blob ,because the Axios package has got some issues you can also check it from github issue.
for me Using the RNFetchBlob did the job i hope it helped

Related

Upload image to a nodeJs server using react-native

I want to upload an image from react-native (cli without expo) to a node server, i tried using axios with formData filed is not recognised by multer, then i tried with fetch that worked image was stored in server but i get promise rejection on front:
const postDocument = (doc) => {
//i used react-native-document-picker to pick document(doc) i logged it and it works
const url =`${api}/sendImage`;
const formData = new FormData();
const id = uuid.v4()
formData.append('id',id)
formData.append('image', doc);
const options = {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
};
fetch(url, options).then((res)=>{
//getting promise rejection even without code but image is stored in backend
}).catch(error=>{})
}
getting this error : [TypeError: Network request failed]
using rn-fetch-blob (react-native-cli not expo-cli) instead of fetch or axios solved this for me

How to send a file to backend in react-native using node.js

I tried
const myData = uri; // this looks like file:///data/expo/...
const myDataResponse = await API.SendFile({
myData: myData
});
But file is not being recieved in the backend. Is there any other way to do this?
IN the backend I get
console.log(req.body)
// I get a string same as uri of file
console.log(req.file)
// undefined
Backend is setup perfectly. I am getting successful response when using postman.
Any help is appreciated. I am a begginer.
You should use FormData.
const data = new FormData();
// first argument is the key name received on you API
// second argument is your file path
data.append('file', filePath)
// then your request should look like this :
await fetch(url, {
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
body: data,
})

Image upload in Nuxt.js using axios

I've tried almost every answer in relative questions, and couldn't find any solution to my case.
I'm new to Nuxt.JS, and I'm moving my project from Vue/CLI to Nuxt.js, now I'm stuck in sending POST request which contains images and data (FormData).
The FormData is appearing empty on the server side (Node.js)
The current working version of my code in Vue CLI:
const requestOptions = {
method: 'POST',
body: formData
};
return fetch(`/create`, requestOptions).then(handleResponse);
What I'm trying to achieve in Nuxt.JS (which is not working properly) by using nuxt/axios module:
methods: {
async sendRequest(){
let formData = new FormData();
formData.append('image',this.myFile);
formData.append('name',this.anyName);
var res = await this.$axios.$post('/create', formData);
}
}
EDIT: I tried to log the content before making the request like:
for (var pair of formData.entries()) {
console.log(pair[0]+ ' - ' + pair[1]);
}
And I can see the fields and values clearly as intended.
I've tried adding headers to the request:
this.$axios.$post('/create', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
But still getting: {} in Node.js while printing the request body.
What I'm doing wrong?

Get image from Axios and send as Form Data to Wordpress API in a Cloud Function

What I'm trying to accomplish is using a Firebase Cloud Function (Node.js) to:
First download an image from an url (f.eg. from unsplash.com) using an axios.get() request
Secondly take that image and upload it to a Wordpress site using the Wordpress Rest API
The problem seems (to me) to be that the formData doesnt actually append any data, but the axios.get() request actually does indeed retrieve a buffered image it seems. Maybe its something wrong I'm doing with the Node.js library form-data or maybe I get the image in the wrong encoding? This is my best (but unsuccessfull) attempt:
async function uploadMediaToWordpress() {
var FormData = require("form-data");
var formData = new FormData();
var response = await axios.get(
"https://images.unsplash.com/photo-1610303785445-41db41838e3e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80"
{ responseType: "arraybuffer" }
);
formData.append("file", response.data);
try {
var uploadedMedia = await axios.post("https://wordpresssite.com/wp-json/wp/v2/media",
formData, {
headers: {
"Content-Disposition": 'form-data; filename="example.jpeg"',
"Content-Type": "image/jpeg",
Authorization: "Bearer <jwt_token>",
},
});
} catch (error) {
console.log(error);
throw new functions.https.HttpsError("failed-precondition", "WP media upload failed");
}
return uploadedMedia.data;
}
I have previously successfully uploaded an image to Wordpress with Javascript in a browser like this:
async function uploadMediaToWordpress() {
let formData = new FormData();
const response = await fetch("https://images.unsplash.com/photo-1610303785445-41db41838e3e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80");
const blob = await response.blob();
const file = new File([blob], "image.jpeg", { type: blob.type });
formData.append("file", file);
var uploadedMedia = await axios.post("https://wordpresssite.com/wp-json/wp/v2/media",
formData, {
headers: {
"Content-Disposition": 'form-data; filename="example.jpeg"',
"Content-Type": "image/jpeg",
Authorization: "Bearer <jwt_token>",
},
});
return uploadedMedia.data;
},
I have tried the last couple of days to get this to work but cannot for the life of me seem to get it right. Any pointer in the right direction would be greatly appreciated!
The "regular" JavaScript code (used in a browser) works because the image is sent as a file (see the new File in your code), but your Node.js code is not really doing that, e.g. the Content-Type value is wrong which should be multipart/form-data; boundary=----...... Nonetheless, instead of trying (hard) with the arraybuffer response, I suggest you to use stream just as in the axios documentation and form-data documentation.
So in your case, you'd want to:
Set stream as the responseType:
axios.get(
'https://images.unsplash.com/photo-1610303785445-41db41838e3e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80',
{ responseType: 'stream' }
)
Use formData.getHeaders() in the headers of your file upload request (to the /wp/v2/media endpoint):
axios.post( 'https://wordpresssite.com/wp-json/wp/v2/media', formData, {
headers: {
...formData.getHeaders(),
Authorization: 'Bearer ...'
},
} )
And because the remote image from Unsplash.com does not use a static name (e.g. image-name.jpg), then you'll need to set the name when you call formData.append():
formData.append( 'file', response.data, 'your-custom-image-name.jpeg' );
I hope that helps, which worked fine for me (using the node command for Node.js version 14.15.4, the latest release as of writing).

How can I improve the elegancy of my code that uses axios?

I am trying to migrate from request to axios, since request has been deprecated.
Suppose that the url 'https://www.example.com' receives a post request with formdata that contains login information, and also suppose that I need to maintain the current session across multiple requests(for that I need a cookieJar).
Using axios I need cookieJar support from an external library therefor I use axios-cookiejar.
Also to send formdata using axios I have to use the external library form-data, and I also have to set the headers manually since axios doesn't do that for me.
I have the following code, which uses axios that does just that:
axios = require('axios')
FormData = require('form-data')
axiosCookieJarSupport = require('axios-cookiejar-support').default
tough = require('tough-cookie')
axiosCookieJarSupport(axios)
cookieJar = new tough.CookieJar()
form = new FormData()
form.append('email', 'example#gmail.com')
form.append('password', '1234')
axios({
method: 'post',
url: 'https://www.example.com',
data: form,
headers: {'Content-Type': `multipart/form-data; boundary=${form._boundary}` },
jar: cookieJar,
withCredentials: true
}).then(function (response) {
console.log(response['data'])
})
Using request this becomes much simpler:
request = require('request')
requestCookieJar = request.jar()
request.post({
url: 'https://www.example.com',
method: 'POST',
jar: requestCookieJar,
formData: {
'email': 'example#gmail.com',
'password': '1234'
}
}, function(error, response, body) {
console.log(body)
})
As you can see the request API is much more elegant.
Is there a way to use axios more elegantly or is there a different elegant API, which isn't deprecated, that I could use to support my needs stated at the beginning of this question?

Resources