React Native uploading Image to php page on server - php

I have PHP page on a web server to upload image from React Native.
Using Postman method POST, form-data key:avatar value: image_file everything works as expected.
In React Native I tried:
let uploadData = new FormData();
uploadData.append('avatar', uploadUri);
fetch(base_url, { method: 'post,', body: uploadData }).then(
(res) => {
var myresponse = res;
console.log(JSON.stringify(myresponse));
//console.log(res);
}
);
I am getting from server error:
{"type":"default","status":400,"ok":false,"headers":{"map":{"server":"Apache","connection":"Upgrade,
close","content-type":"text/html","vary":"Accept-Encoding,User-Agent","date":"Wed,
20 May 2020 15:29:15
GMT","accept-ranges":"bytes","upgrade":"h2,h2c"}},"url":"http://www./uploadImage.php","_bodyInit":{"_data":{"size":10154,"offset":0,"blobId":"D8041FEE-0479-4CD5-8438-4EFD737561DE","type":"text/html","name":"uploadImage.php","__collector":{}}},"_bodyBlob":{"_data":{"size":10154,"offset":0,"blobId":"D8041FEE-0479-4CD5-8438-4EFD737561DE","type":"text/html","name":"uploadImage.php","__collector":{}}}}
Than I tried using axios:
let uploadData = new FormData();
uploadData.append('avatar', uploadUri);
axios.post(base_url, uploadData).then((res) => {
console.log(res);
});
I get this response from the server:
"error": true,
"message": "No file was sent!",
"status": "error",
It is failing on: if($_FILES['avatar']), in PHP.
I have no idea what to do any more, again in Postman everything works fine as expected.
Does anybody have any idea what to do?
I tested it again and it is to be a problem with the URI that I am sending, for sure.
ie. if I look in Postman the request that I am sending:
avatar=#/Users/......image.jpg
and in React Native I am sending:
"avatar","file:///Users/.....image.jpg
By the way, I am using expo-image-picker to select the image.

It looks like this did the work..
let body = new FormData();
//Appending file to body
body.append('avatar', {
uri: uploadUri,
type: 'image/jpeg', //This is the file type .. you can define according to your requirement
name: 'avatar.jpg', //File name you want to pass
});
//Service call
fetch(base_url, {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded',
}),
body: body,
})
.then((res) => res.json())
.then((responseJson) => {
//GET RESPONSE SUCCESS OF FAILURE
console.log(JSON.stringify(responseJson));
})
.catch((error) => {
//ERROR
console.log(JSON.stringify(error));
});

Related

axios/ fetch failed but postman work with php api

I got stuck when calling php api with form-data type in my React app. When I test with Postman, it works correctly but failed in react.
Please let me know if I'm doing wrong here.
In Postman, call api like this:
URl_API: xxxx/yyyy.php.
Config in Body tab in key/value: form-data
k: "some string"
id: "some string"
With axios, I had an error:
My code:
const formData = new FormData()
formData.append('k', 'some string')
formData.append('id', 'some string')
const response = await axios.post('xxxx/yyyy.php', formData, {
headers: {
'Access-Control-Allow-Origin': '*',
},
})
xxxx/yyyy.php net::ERR_HTTP2_PROTOCOL_ERROR
I had already tried with fetch but no luck - call api success with status 200 but the response.text() is empty.
With fetch api:
const result = await fetch('xxxx/yyyy.php', {
method: 'POST',
mode: 'no-cors',
body: formData,
cache: 'no-cache',
})
.then(async (res) => {
return res.text()
})
.then((text) => console.log('It is empty here', text))
It look like a CORS also, but you will be able to sort it out
a simple solution in development is to use a local api server, and finally when the app is deployed to the server which is on the same domain as the api, you should get the response, as demonstrated below by making the calls using dev tools.
in short: if a api calls work with postman but not through the browser, its mostly due to cors restrictions, then it could be the response type
Verifying cors issue by making calls throught dev tools
let onSubmit = async () => {
try {
const url = "https://www.your-domain***.com/getUrlApp.php";
const formData = new FormData();
formData.append("k", "kk");
formData.append("id", "dd");
const data = new URLSearchParams(formData);
const response = await fetch(url, {
method: "POST", // *GET, POST, PUT, DELETE, etc.
mode: "no-cors", // no-cors, *cors, same-origin
body: data // body data type must match "Content-Type" header
});
//const res = response.json();
const buffer = await response.arrayBuffer();
const decoder = new TextDecoder("iso-8859-1");
const text = decoder.decode(buffer);
console.log("text", text);
return response;
} catch (error) {
console.log("error", error);
}
};
To verify the response
go https://www.your-domain***.com
open dev tools => console
past the function above and run it by typing onSubmit() in the console
you will see the response
Hope it helps you in some way

How to get file from Form Data in the server

I cant get the file data on the server. _$FILE says is empty. I do this trough ionic app. I send the information in http params.
cargarFoto(idnegocio,formData) {
let datos = new HttpParams()
.set("proceso", "subirImgNegocioApp")
.set("imgRestaurante", formData)
.set("idnegocio", idnegocio)
let headerOptions = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(this.path,datos, {
observe: 'response',
responseType: 'text',
headers: headerOptions
});
}
That is the code from my service where i send the form Data and other information.
But when i use $_FILES to get the file, it says is null or empty. What im doing wrong? Actually all the information is get on $_POST. I returned post to the app and this is what displays:
body: "{
"proceso": "subirImgNegocioApp",
"imgRestaurante": "[object FormData]",
"idnegocio": "4"
}"
I can suggest little different approach - send everything as form data:
sendSomething(someVar: string, files: File[]) {
const formData = new FormData();
for (const f of files) {
formData.append('file[]', f);
}
formData.append('someVar', someVar);
return this.http.post('/someUrl', formData, {
headers: new HttpHeaders({ enctype: 'multipart/form-data' })
});
}
Then in PHP:
$someVar = $_REQUEST['someVar']
And files (or one file) will be in
$_FILES['file']

The variables never reach PHP from the FETCH API

I have 3 files (HTML,JS and PHP) in the HTML save de info in variable called DatosPaciente in JavaScript
function Tomar_DATOS(){
DatosPaciente={
id:document.getElementById("paciente_id").value,
fecha:document.getElementById("fecha").value
};}
Then i use a function called Tiene_Cita_Hoy inside of a JS file
Tiene_Cita_Hoy(DatosPaciente)
in the JS file i try to use the Fetch API to send info to the PHP file
function Tiene_Cita_Hoy(Datos){
console.log(Datos);//"{id: "8", fecha: "2020/09/03"}" here everything is fine
fetch('tiene_cita.php',{
method: 'POST',
body: Datos
})
.then(res => res.json())
.then(data => {
console.log(data); //to see the result
})
}
then in a PHP file, then tried to receive the information via POST
$VALOR_id_paciente=$_POST['id'];
$VALOR_fecha=$_POST['fecha'];
and then I assign those values ​​to a query
$SQL="SELECT * FROM vhsagenda WHERE PACIENTE='".$VALOR_id_paciente."' AND FECHA='".$VALOR_fecha."'";
echo json_encode($SQL);//just to see what information have
but the result is always: SELECT * FROM vhsagenda WHERE PACIENTE='' AND FECHA=''
apparently the information never reaches the PHP file
I have made some proper way for this method to get working.
You need to make an object first, then pass it in 'for loop'. It will generate string like this for example (test=123&test_two=444)
async function catch_something(url, bodyContent = {test: 123, test_two: 444}){
let bodyContent_string = '';
if(bodyContent instanceof Object){
for(const form_key of Object.keys(bodyContent)){
if(form_key != Object.keys(bodyContent)[Object.keys(bodyContent).length - 1]){
bodyContent_string += `${form_key}=${bodyContent[form_key]}&`;
}else{
bodyContent_string += `${form_key}=${bodyContent[form_key]}`;
}
}
}
const response = await fetch(url, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: bodyContent_string
}).catch((error) => {
console.error('Error:', error);
});
if(!response.ok){
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
You should send the parameters as a URL-encoded string.
function Tomar_DATOS(){
DatosPaciente = 'id=' + encodeURIComponent(document.getElementById("paciente_id").value) + '&fecha=' + encodeURIComponent(document.getElementById("fecha").value);
}
You've passed a plain object to the body parameter, but fetch doesn't know what to do with that data type (so it converts it to the useless string "[object Object]").
You should pass something that fetch knows how to convert into something supported by PHP instead.
e.g. a FormData object.
DatosPaciente = new FormData(document.getElementById("form_containing_your_inputs"));

Image upload issue with react-native and PHP(CodeIgniter) as backend

I have an app scenario with react native and CodeIgniter as backend.
I have a code snippet to upload image as picked by react-native-image-picker as below:
let formData = new FormData();
let imageBody = {
uri: newImage,
name: 'profilepicture.jpg',
type: 'image/jpeg',
};
formData.append('file', (imageBody)) // case 1 gives network error
formData.append('file', JSON.stringify(imageBody)) //case 2 goes OK
apiUpdateUser(formData)
.then(res => {
this.setState({ showSnack: true, snackText: 'Profile Picture Updated'})
})
.catch(err => {
this.setState({ showSnack: true, snackText: 'Update Failed' })
});
The apiUpdateUser method goes as :
export const apiUpdateUser = body => {
return new Promise((resolve, reject) => {
axios
.post(ApiRoutes.updateUser, body, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(Constant.network.networkError);
});
});
};
The Php code at the backend to handle this upload as usual is:
$file=$this->request->getFile('file');//in CI
$file=$_FILES['file'];//in normal php
My issue is that I do not get anything whatsoever in the $file variabe with either of the methods, The file variable is empty in both the cases.
I've checked the implementation in react native and it doesnt seem to be buggy at all comparing with tutorials/demonstrations online. Also the way of handling at the backend is obvious and Ok.
I'm able to achieve this upload with POSTMAN easily but with react-native I'm facing this error. Can anyone show me some light here??
I am using VUE and sending files using Axios. So I think this may help you out.
I am using the following way of form data to set the files or images.
formData.append('file', this.form.image_url, this.form.image_url.name);
Here this.form.image_url directly refers to the $event.target.files[0]; where $event targets the input.
In the backend, it is the same as you have it here.
This works out well for me. I am unsure of what you are passing as imageBody so it's hard to comment on that.
You can try this
let imageBody = {
uri: newImage,
name: 'profilepicture.jpg',
type: 'image/jpeg',
};
apiUpdateUser(imageBody)
.then(res => {
this.setState({ showSnack: true, snackText: 'Profile Picture Updated'})
})
.catch(err => {
this.setState({ showSnack: true, snackText: 'Update Failed' })
});
export const apiUpdateUser = body => {
return new Promise((resolve, reject) => {
axios
.post(ApiRoutes.updateUser, body, {
headers: {
'Content-Type': 'application/json'
}
})
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(Constant.network.networkError);
});
});
};
Turns out that the JSON.stringify() was the culprit line.
Without that line, the app was giving out network error.
That's why I had randomly added it just to see if that was the cause of error.
Since, the network error issue was solved with that addition, I didn't give a second thought about it and only thought it to be a file upload issue. Actually, I now see that this is a known issue of a react native flipper version that I have been using which I managed to solve.

TypeError: Network request failed using fetch ReactNative and Laravel response

I am posting data to Laravel and expect a success response, but it catches the exception TypeError: Network request failed. Using get methods and login post methods using Laravel passport works all fine.
Adding 'Content-Type': 'application/json' to headers creates Network request failed for the login methods.
Postman returns valid errors or success, so works totally as expected.
Debugging showed that the request has been sent to Laravel and routing is correct as Visual Studio Code debugger stops at a breakpoint at return response.
public function postMessages()
{
...
return response()->json(['success' => 'success'], 200);
}
Route::middleware('auth:api')->group(function () {
Route::post('messages', 'Api\ChatController#postMessages');
});
export const fetchApi = async (endPoint, method = 'get', body = {}) => {
const accessToken = authSelectors.get().tokens.access.value;
const accessType = authSelectors.get().tokens.access.type;
let headers = {
...(accessToken &&
{
Authorization: `${accessType} ${accessToken}`
}
)
};
let response;
if (method=='get' || Object.keys(body)==0 ) {
response = await fetch(`${apiConfig.url}${endPoint}`, {
method: method,
headers: headers
});
} else {
var formData = new FormData();
Object.keys(body).forEach(type => {
formData.append(type, body[type]);
});
response = await fetch(`${apiConfig.url}${endPoint}`, {
method: method,
headers: headers,
body: formData
});
console.log('fetch response: ' + JSON.stringify(response));
}
let responseJsonData = await response.json();
return responseJsonData;
}
export const postMessages = (eidug, type, name, messages) => fetchApi('/message', 'post', {
'eidug': eidug,
'type': type,
'name': name,
'messages': messages
});
I expect a response without any exception like Postman. What can be going wrong?
Have you enabled CORS in the backend? Once open inspect->network and then run fetch. Show if there are any errors.

Categories