0

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:

[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:

    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?

Laney Williams
  • 573
  • 3
  • 13
  • 34
  • 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 Jul 02 '18 at 12:38
  • See https://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 Jul 02 '18 at 12:48
  • Sorry, I meant `$_FILES`, not `$FILES`. – Raphael Schweikert Jul 02 '18 at 12:51

1 Answers1

0

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.

Rajat Gupta
  • 1,864
  • 1
  • 9
  • 17
  • 1
    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 Jul 02 '18 at 12:54