0

Before everything , I know that my question is already posted thousand times but none of them concern me since i cant identify my problem.

So ,I am building a PHP rest api to get a put request from the client (angular), this last can update a file inside the form as well as some text inputs , all of this is sent as a form-data in this code :

var fileFormData = new FormData();
$http({
  method: 'PUT',
  url: host + '/produit/' + $scope.product.id,
  data: fileFormData,
  transformRequest: angular.identity,
  headers: {
    'Content-Type': undefined
  }
}).then(function successCallback(response) {}, function errorCallback(response) {});

On the server-side I have to get the response type and then parse the data here's the full code with help from here

$method = $_SERVER['REQUEST_METHOD'];
if ($method=="PUT"){
global $_PUT;

/* PUT data comes in on the stdin stream */
$putdata = fopen("php://input", "r");

/* Open a file for writing */
// $fp = fopen("myputfile.ext", "w");

$raw_data = '';

/* Read the data 1 KB at a time
   and write to the file */
while ($chunk = fread($putdata, 1024))
    $raw_data .= $chunk;

/* Close the streams */
fclose($putdata);

// Fetch content and determine boundary
$boundary = substr($raw_data, 0, strpos($raw_data, "\r\n"));

if(empty($boundary)){
    parse_str($raw_data,$data);
    $GLOBALS[ '_PUT' ] = $data;
    return;
}

// Fetch each part
$parts = array_slice(explode($boundary, $raw_data), 1);
$data = array();

foreach ($parts as $part) {
    // If this is the last part, break
    if ($part == "--\r\n") break;

    // Separate content from headers
    $part = ltrim($part, "\r\n");
    list($raw_headers, $body) = explode("\r\n\r\n", $part, 2);

    // Parse the headers list
    $raw_headers = explode("\r\n", $raw_headers);
    $headers = array();
    foreach ($raw_headers as $header) {
        list($name, $value) = explode(':', $header);
        $headers[strtolower($name)] = ltrim($value, ' ');
    }

    // Parse the Content-Disposition to get the field name, etc.
    if (isset($headers['content-disposition'])) {
        $filename = null;
        $tmp_name = null;
        preg_match(
            '/^(.+); *name="([^"]+)"(; *filename="([^"]+)")?/',
            $headers['content-disposition'],
            $matches
        );
        list(, $type, $name) = $matches;

        //Parse File
        if( isset($matches[4]) )
        {
            //if labeled the same as previous, skip
            if( isset( $_FILES[ $matches[ 2 ] ] ) )
            {
                continue;
            }

            //get filename
            $filename = $matches[4];

            //get tmp name
            $filename_parts = pathinfo( $filename );
            $tmp_name = tempnam( ini_get('upload_tmp_dir'), $filename_parts['filename']);

            //populate $_FILES with information, size may be off in multibyte situation
            $_FILES[ $matches[ 2 ] ] = array(
                'error'=>0,
                'name'=>$filename,
                'tmp_name'=>$tmp_name,
                'size'=>strlen( $body ),
                'type'=>$value
            );

            //place in temporary directory
            file_put_contents($tmp_name, $body);


        }
        //Parse Field
        else
        {
            $data[$name] = substr($body, 0, strlen($body) - 2);
        }

    }

}
$GLOBALS[ '_PUT' ] = $data;
 $input= array_merge($_PUT, $_FILES);
 }

and then I have to execute the query and move the file form the temp folder

$sql = "update `$table` set $set where id=$key"; //works    
if(isset($name)){ //to check if file exist
chmod($tmpname,0666); //since that's the answer for most of question that are similar to mine
echo substr(sprintf('%o', fileperms($tmpname)), -4); //returns 0666
echo $tmpname." ".$name; //works too
if(move_uploaded_file($tmpname, "/home/****/****/uploads/produits/".$name))
echo "moved";
else 
echo "not moved"; // and I always get this  

Can you explain to me please whats wrong ?

PS: I checked the /tmp folder the files I uploaded are still there.
The log is clean and I used this in the top of my code

ini_set('display_errors', true);
error_reporting(E_ALL);

Update :

I use this to get file params from the $input var

$values = array_map(function ($value) use ($link) {
     global $method;
    if ($value === null)
        return null;
    if (gettype($value) === "array"){
         if ($method=="PUT" || $method=="POST"){            
        global $tmpname,$name;
        $tmpname=$value['tmp_name'];
        $name=uniqid().$value['name'];
       $value=$name;
         }
    }
    return mysqli_real_escape_string($link, (string) $value);
}, array_values($input));
Neji Soltani
  • 1,522
  • 4
  • 22
  • 41

0 Answers0