upload image from react native app to symfony backend via axios - react-native

I want to upload an image from react native app to backend in symfony via axios.
here is the code of the front end :
const [pickedImage, setPickedImage] = useState("");
const submitPhoto = async () => {
try {
const result = await ImagePicker.launchImageLibraryAsync();
setPickedImage(result);
let formData = new FormData();
formData.append("uploaded_image", {
uri:
Platform.OS === "android"
? pickedImage.uri
: pickedImage.uri.replace("file://", ""),
name: "tata.jpeg",
type: "image/jpeg",
});
const response = await axios({
method: "post",
url: "http://192.168.1.3:8000/upload",
data: formData,
});
} catch (error) {
console.log(error)
}
};
here is the code of the backend in Symfony :
public function postImage(Request $request)
{
//... some code
$content = $request->files->get("uploaded_image");
// ... handle the image in content
}
As I can see, $content is NULL. And to confirm it, I attached a screenshot of the profiler of symfony.
I tried to add "Content-type": "multipart/form-data" in the axios call, but i get : "Missing boundary in multipart/form-data POST data"
Does anyone know how I can properly upload the image from react native to Symfony ?
Thanks in advance.
EDIT 1 :
When using POSTMAN, the backend works as you can see in the two following images :
POSTMAN REQUEST :
PROFILER SYMFONY :

As I said, when i use Axios with the right header (multipart/form-data), I get a message error :
Missing boundary in multipart/form-data POST data
.
I tried to use fetch, and it works now ! I dont know why :
let response = await fetch(
"http://192.168.1.3:8000/upload",
{
method: "post",
body: formData,
headers : {
'Content-Type' : 'multipart/form-data;'
}
}
)
It is weird, but I dont know why it works now.

I think that you get a base64 in your back-end side, then you have to convert it with something like :
$data = base64_decode($content);
file_put_contents($filePath, $data);

Related

How to use Nuxt 3 server as a passthrough API with FormData to hide external endpoints

I'm trying to get my head around the Nuxt /server API and can't seem to figure out how to send a POST request with form-data (ie files) to Nuxt server to forward on to an external service:
In my pages.vue file I have this method:
async function onSubmit() {
const formData = new FormData();
for (let file of form.files) {
await formData.append("image", file);
}
await $fetch("/api/send", {
method: "POST",
body: formData
});
}
and then in /server/api/send.js I have:
export default defineEventHandler(async (event) => {
const { method } = event.node.req;
// I THINK THE ISSUE IS HERE
const body =
method !== "GET" && method !== "HEAD"
? await readMultipartFormData(event)
: undefined;
const response = await $fetch.raw(https://*******, {
method,
baseURL: *********,
headers: {
},
body: body
});
return response._data;
}
I'm effectively creating a passthrough API using Nuxt so that the external endpoint isn't exposed to the end user. Just can't figure out how to access the formData in the correct format to pass through on the server side. I don't think I am supposed to use readMultipartFormData() because that seems to be parsing the data somehow whereas I just want to pass the formData straight through to the external API. Any tips?
I've tried using both readMultipartFormData() and readBody() and neither seem to work. I don't actually need to read the body but rather get it and pass it through without any formatting...
If you want to pass the data with formdata to the endpoint try this library:
https://www.npmjs.com/package/object-to-formdata
code:
import { serialize } from 'object-to-formdata';
const formData = serialize(body);
const response = await $fetch.raw(https://*******, {
method,
baseURL: *********,
headers: {
},
body: formData
});
I managed to make it work with ugly solution, first you have to update nuxt to version 3.2.0 min then here my front side
let jobApplicationDTO = {
firstName: values.firstName,
lastName: values.lastName,
email: values.email,
phoneNumber: values.phoneNumber,
company: values.company,
shortDescription: values.shortDescription
};
const formData = new FormData();
formData.append("application", new Blob([JSON.stringify(jobApplicationDTO)], {type: "application/json"}));
formData.append("file", values.file) ;
//formData.append("file", values.file );
await useFetch("/api/application", {
method: "POST",
body: formData,
onResponse({request, response, options}) {
// Process the response data
if (response.status === 200) {
errorMessage.value = "";
successMessage.value = "Your application wa sent successfully, you will be contacted soon !";
}
},
onResponseError({request, response, options}) {
console.debug(response);
if (response.status === 400) {
successMessage.value = "";
errorMessage.value = "There may be an issue with our server. Please try again later, or send an email to support#mantiq.com";
} else {
successMessage.value = "";
errorMessage.value = "Sorry we couldn’t send the message, there may be an issue with our server. Please try again later, or send an email to support#mantiq.com";
}
},
});
}
and server side
import {FormData} from "node-fetch-native";
export default defineEventHandler(async (event) => {
const {BACKEND_REST_API, ENQUIRY_TOKEN} = useRuntimeConfig();
//retrieve frontend post formData
const form = await readMultipartFormData(event);
const applicationUrl = BACKEND_REST_API + '/job/apply'
console.log("url used for enquiry rest call :" + applicationUrl);
console.log("Job application token :" + ENQUIRY_TOKEN);
const formData = new FormData();
console.log(form);
if (form) {
formData.append(form[0].name, new Blob([JSON.stringify(JSON.parse(form[0].data))], {type: form[0].type}));
formData.append(form[1].name, new Blob([form[1].data], {type: form[1].type}), form[1].filename);
}
console.log(formData.values);
return await $fetch(applicationUrl, {
method: "POST",
body: formData,
headers: {
Authorization: ENQUIRY_TOKEN,
},
});
})
What is funny is on frontend you have to create a formData , then to get content and to recreate a formData from your previous formData converted in MultiFormPart[], i created a ticket on nuxt to see how to do it properly

Not Getting anything back after calling Fetch API - React Native

I am creating a React Native in which i am sending my Form's data to Backend Node.js using Fetch and that worked all fine but i cannot execute anything down after fetch api, even console.log is not running.
React-Native Code:
const PostData = () =>{
console.log("Posting");
//Sending Request to Node.js using Fetch API
fetch("http://192.168.0.107:3000/Adminsignup", {
//Setting Method
method:"POST",
//Setting Headers
headers:{
//Setting Content-Type
"Content-Type" : "application/json"
},
//Stringifying the email and password and storing it into body
body:JSON.stringify({
name,
gmail,
password,
retype
})
}).then(res=>{
console.log(res);
}).catch(err=>{
console.log(err);
})
}
.then and .catch of fetch api is not working.
Ok so your front-end code is all good and as u said that your backend is also working when you fire PostData() function, check if you are returning the response from backend.
Add this in your signup Route:
res.status(200).send({result:"Successfully got Response"})
Catch status in your front-end like this:
let final = await fetch("http://192.168.0.107:5000/studentSignup", {
//Setting Method
method:"POST",
//Setting Headers
headers:{
//Setting Content-Type
"Content-Type" : "application/json"
},
//Stringifying the email and password and storing it into body
body:JSON.stringify({name,gmail,password,retype})
})
const data = final.status;
if(data === 200)
{
navigation.navigate("Your Route");
}

react native getting network error when sending files with axios

i'm using api platform to create end Point to handle images upload.
My api require a file type to make a post request.
This is an example of post request using post man :
I want to handle sending images with axios using react native.
I created a post request like this :
this.setState({
avatarSource: source,
});
console.log(this.state.avatarSource.uri);
const data = new FormData();
data.append('file', {
uri: this.state.avatarSource.uri,
// show full image path in my device
// file:///storage/emulated/0/Pictures/image-c40b64fc-6d74-46a7-9016-191aff3740dd.jpg
});
axios
.post(`${API.URL}/media_objects`, data, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
.then((resp) => console.log(resp))
.catch((err) => console.log(err.message));
}
});
I'm sending the full path of image in my phone to the api but i got "Network Error"
I fixed the problem by commenting this line in ReactNativeFlipper.java :
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
#Override
public void apply(OkHttpClient.Builder builder) {
// builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); // add comment here and build android
}
});
client.addPlugin(networkFlipperPlugin);
client.start();

React Native fetch POST variables not received on server

I have tried different ways with fetch or axios to POST to my server but it seems that the post body turns empty . My initial code is this.
So the connection to the server is good. I have configured server to respond with $_POST variables received but the $_POST return empty. This happens when I use JSON.stringify on body. I have also tried with FormData and it works fine but only on iOS. On my Android device and emulator I get Possible Unhandled Promise: Network request failed error (both https and http).
And I want to make it work on both iOS and Android. So till now I have manage to send post with formData only on iOS.
Any Solutions that works on Android and iOS?
import FormData from "FormData";
export const login = (emailUsername, password) => {
var formData = new FormData();
formData.append("emailUsername", emailUsername);
formData.append("password", password);
return async dispatch => {
const response = await fetch(
"https://myserver.net/api/app/auth.php",
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
emailUsername:emailUsername,
password:password
})
}
);
if (!response.ok) {
throw new Error("Something went wrong!");
}
const resData = await response.json();
console.log(resData);
};
};
Thanks to #bug I have find a solution. I was expecting to receive POST content to my $_POST or $_REQUEST variables on my server, but instead I had to get them this way.
$post_data = json_decode(file_get_contents('php://input'));

Post to /upload from react native

I'm trying to upload a picture to strapi from react native.
async function uploadPicture(uri) {
var data = new FormData();
data.append('files', {
uri: uri.replace('file://', ''),
name: uri,
type: 'image/jpg'
});
// Create the config object for the POST
// You typically have an OAuth2 token that you use for authentication
const config = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data;'
},
body: data
};
const fetchPromise = fetch('http://<host>:1337/upload', config)
console.log(fetchPromise)
return await fetchPromise
}
I get a 200 status code but no new picture is listed on the uploads page.
Oh! I figured it out using simple-http-upload-server to test the uploads. The problem was that I was setting the name of the file to be the uri. This would probably cause an error on strapi when creating the file on the server folder. It should return an error code nonetheless.