PHP receiving null data from React Native while uploading images?


PHP receiving null data from React Native while uploading images?



This took me a while to figure out because on the app screen all I was getting was JSON Parse Error: '<'. Thanks to the error_log, I found these errors in PHP:


JSON Parse Error: '<'


error_log


[29-Jun-2018 19:35:34 America/Chicago] PHP Deprecated: Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream instead. in Unknown on line 0
[29-Jun-2018 19:35:34 America/Chicago] PHP Warning: explode() expects parameter 2 to be string, array given in React/user-image-upload.php on line 17
[29-Jun-2018 19:35:34 America/Chicago] PHP Warning: end() expects parameter 1 to be array, null given in React/user-image-upload.php on line 18
[29-Jun-2018 19:35:34 America/Chicago] PHP Warning: preg_match() expects parameter 2 to be string, array given in React/user-image-upload.php on line 27
[29-Jun-2018 19:35:34 America/Chicago] PHP Warning: unlink() expects parameter 1 to be a valid path, array given in React/user-image-upload.php on line 30



And here is my php code for uploading the images:


<?php
// Getting the received JSON into $json variable.
$json = file_get_contents('php://input');

// decoding the received JSON and store into $obj variable.
$obj = json_decode($json,true);

$fileName = $obj["userimgSource"]; // The file name
$fileTmpLoc = $obj["userimgSource"]; // File in the PHP tmp folder
$fileType = $obj["userimgSourceType"]; // The type of file it is
$fileSize = $obj["userimgSourceSize"]; // File size in bytes
$fileErrorMsg = $_FILES["uploaded_file"]["error"]; // 0 for false... and 1 for true
$kaboom = explode(".", $fileName); // Split file name into an array using the dot
$fileExt = end($kaboom); // Now target the last array element to get the file extension
// START PHP Image Upload Error Handling --------------------------------------------------
if (!$fileTmpLoc) { // if file not chosen
echo json_encode("ERROR: Please browse for a file before clicking the upload button.");
exit();
} else if($fileSize > 5242880) { // if file size is larger than 5 Megabytes
echo json_encode("ERROR: Your file was larger than 5 Megabytes in size.");
unlink($fileTmpLoc); // Remove the uploaded file from the PHP temp folder
exit();
} else if (!preg_match("/.(gif|jpg|jpe|jpeg|png)$/i", $fileName) ) {
// This condition is only if you wish to allow uploading of specific file types
echo json_encode("ERROR: Your image was not .gif, .jpg, .jpe, or .png.");
unlink($fileTmpLoc); // Remove the uploaded file from the PHP temp folder
exit();
}
// END PHP Image Upload Error Handling ----------------------------------------------------
// Place it into your "uploads" folder mow using the move_uploaded_file() function
$moveResult = move_uploaded_file($fileTmpLoc, "../profiles/uploads/$fileName");
// Check to make sure the move result is true before continuing
if ($moveResult != true) {
echo json_encode("ERROR: File not uploaded. Try again.");
unlink($fileTmpLoc); // Remove the uploaded file from the PHP temp folder
exit();
}
if ($moveResult == true) {
$db = mysqli_connect("localhost", "root", "password", "photos");
$sql = "INSERT INTO user_images (images,date) VALUES ('$fileName',CURDATE())";
mysqli_query($db, $sql);
echo json_encode("Success: File uploaded.");

}
unlink($fileTmpLoc); // Remove the uploaded file from the PHP temp folder
?>



Before I show you all my react native code I just want to say that I am unfamiliar when it comes image uploading in RN. I read many questions on SO to find out how to do it and watched some youtube videos. I don't know if I am supposed to use base64 (if anyone can explain that to me that would be great), to my knowledge I am just pulling the image path, the image size, and image type then inserting that image path to my folder and the database:


base64


SelectPhoto = () =>{
ImagePicker.openPicker({
cropping: true,
title: 'Select an image',
isCamera: true,
}).then((imgResponse) => {
console.log(imgResponse);
let imgSource = { uri: imgResponse[0].path.replace(/^.*[/]/, '') };
this.setState({
userimgSource: imgSource,
userimgSourceType: imgResponse[0].mime,
userimgSourceSize: imgResponse[0].size,
});
});


}

UploadPhoto = () =>{
fetch('https://www.example.com/React/user-image-upload.php', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
userimgSource : this.state.userimgSource,
userimgSourceType: this.state.userimgSourceType,
userimgSourceSize: this.state.userimgSourceSize,

})

}).then((response) => response.json())
.then((responseJson) => {

// Showing response message coming from server after inserting records.
Alert.alert(responseJson);


}).catch((error) => {
console.error(error);
});
}



Here is where the confusion comes in. When I console.log my userimgSource: imgSource, userimgSourceType: imgResponse[0].mime, userimgSourceSize: imgResponse[0].size, I, in fact, do get the correct data. I get the image path: IMG_2018629.png, the mime: image/png, and the size: 2,097,152. Is there a reason why PHP is not able to pick up the data from what was given in React Native?


console.log


userimgSource: imgSource, userimgSourceType: imgResponse[0].mime, userimgSourceSize: imgResponse[0].size,


IMG_2018629.png


image/png


2,097,152





You’re mixing two things here. PHP will only populate $FILES when the POST body contains files posted using Content-Type multipart/form-data (standard MIME format). You are, however, sending JSON (in PHP you’re also expecting JSON POST data via file_get_contents('php://input')). So either remove usage of $FILES and post your image in as Base64-encoded JSON strings or use real multipart/form-data (I think this is preferable as it allows you to post binary data without conversion and allows you to use built-in PHP file handling).
– Raphael Schweikert
yesterday


$FILES


multipart/form-data


file_get_contents('php://input')


$FILES


multipart/form-data





See stackoverflow.com/a/26261002/11940 for more info about how to really prevent $HTTP_RAW_POST_DATA from being populated: set always_populate_raw_post_data to -1 in php.ini, as the message suggests. Setting it to off or 0 only prevents that for POSTs with known Content-Types (which, apparently, application/json isn’t one of).
– Raphael Schweikert
yesterday



$HTTP_RAW_POST_DATA


always_populate_raw_post_data


-1


Content-Types


application/json





Sorry, I meant $_FILES, not $FILES.
– Raphael Schweikert
yesterday


$_FILES


$FILES




1 Answer
1



Change your headers to this




headers: {
'Accept': '*',
'Content-Type': 'multipart/form-data',
}



As you are upload image its content-type cannot be
'application/json'.



The Accept request-header field can be used to specify certain media types which are acceptable for the response. So adding star will make your request to accept any type of response.





This solution will only change the headers sent with the request but the data will still be JSON. Since the headers are ignored by the OP’s code anyway, nothing will actually change…
– Raphael Schweikert
yesterday






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

Export result set on Dbeaver to CSV

Opening a url is failing in Swift