skip to Main Content

Maybe someone can help me? I do not get on with this problem

I have a POST array from a formualar and a file already existing on the server.
The task is to send the POST data and the file via CURL PUT to a URL.

I’ve been trying to solve the problem for hours/days now

I have set the header Content-type: application/octet-stream and the fields with $ch->setOption(CURLOPT_POSTFIELDS, http_build_query($data)

The POST data looks like this:

$data = array (
  'field1' => 'lorem',
  'field2' => 'ipsum',
  'field3' => 'dolor'
);

Using instructions (php.net, stackoverflow etc.)

https://kb.detlus.com/articles/php/upload-files-using-curl/

https://www.php.net/manual/de/curlfile.construct.php

Is it possible to use cURL to stream upload a file using POST?

I try to send the file

Does not work

$data = array (
  'field1' => 'lorem',
  'field2' => 'ipsum',
  'field3' => 'dolor'
  'file' => '@'.realpath('/abs/path/file.xlsx');
);

neither

$data = array (
  'field1' => 'lorem',
  'field2' => 'ipsum',
  'field3' => 'dolor'
);

$data['file'] = curl_file_create('/abs/path/file.xlsx'], mime_content_type('/abs/path/file.xlsx'), 'file.xlsx');

this leads to the following array

$data = array (
  'field1' => 'lorem',
  'field2' => 'ipsum',
  'field3' => 'dolor',
  'file' => 
  array (
    'file' => 
    CURLFile::__set_state(array(
       'name' => '/abs/path/file.xlsx',
       'mime' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
       'postname' => '/abs/path/file.xlsx',
    )),
  )
);

Depending on the version I try I get a 400 or 500 error.

Does anyone have a tip that can help me?
What am I doing wrong?

2

Answers


  1. Chosen as BEST ANSWER

    Thanks for your help!!! Solution => Content-Type: multipart/form-data


  2. I think the main problem here is that you’re using the wrong content type.

    For file uploads you should be using "Content-Type: multipart/form-data".
    Taken from Wikipedia (in the multipart subtypes) MIME

    The MIME type multipart/form-data is used to express values submitted through a form. Originally defined as part of HTML 4.0, it is most commonly used for submitting files with HTTP. It is specified in RFC 7578, superseding RFC 2388.

    I wrote this snippet, hope this can help you (sorry for the non-OOP version of the code, I don’t have a PHP 8 install, I’m using PHP 7.4, but you can "translate" it easily :D):

    <?php
    //This is a dummy data array, will contain your form fields (Advice: never trust user input, always check the values given before submitting)
    $data = [
        'field1' => 'value',
        'field2' => 'value2',
        'field3' => 123
    ];
    
    //The path to the file you want to upload
    $fileName = 'somefile.xlsx';
    $filePath = './../files/'.$fileName;
    
    //Security check
    if (file_exists($filePath))
    {
        //Adding the file to the $data array
        $data['file'] = curl_file_create($filePath, mime_content_type($filePath), $fileName);
    
        //Initialize the cURL handle
        $ch = curl_init('https://some-random-site.com/api/some/random/endpoint');
    
        //Set the request method (HTTP verb)
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
    
        //This will make curl "return" the response as string when we call curl_exec()
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
        //This SHALL NOT be used in production, unless you know the implications!!! But, if you have an HTTPS endpoint with a self-signed certificate you can skip checks
        //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        //======
    
        //We set the data we want to send (curl will "transform" this for us
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    
        //Here the important part, setting the right content-type
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: multipart/form-data']);
    
        //Execute the call and get the response as string
        $res = curl_exec($ch);
        if ($res === false)
        {
            //An error occurred, print out
            echo 'ERROR: '.curl_error($ch);
        }
        else
        {
            //Execution succeeded, do whatever with the response
            //Hint: this does not mean that the server answered with a success status but rather, it indicates that the curl execution has succeeded
    
            //If you want to check the HTTP status of the request you can get it like this:
            //$info = curl_getinfo($curl);
            //echo $info['http_code'];
    
            //Do whatever with the response (I'm just printing it).
            echo $res;
        }
    
        curl_close($ch);
    }
    else
    {
        echo 'File not found.';
    }
    

    I really hope this can help, unfortunately I don’t know the URL/API you’re submitting the request to so I can’t test it on your endpoint. I made an endpoint myself:

    <?php
    if ($_SERVER['REQUEST_METHOD'] === 'PUT')
    {
        $c = file_get_contents('php://input');
        die(var_dump($c));
    }
    

    The output I got showed me all the fields and the file upload.

    --------------------------05a7619c906d94df Content-Disposition: form-data; name="field1" value
    
     --------------------------05a7619c906d94df Content-Disposition: form-data; name="field2" value2
    
     --------------------------05a7619c906d94df Content-Disposition: form-data; name="field3" 123
    
     --------------------------05a7619c906d94df Content-Disposition: form-data; name="file"; filename="./../conf/test.xlsx" Content-Type:
     application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
     ........LOTS_OF_BYTES_OF_THE_XLSX_FILE_:P......
     --------------------------05a7619c906d94df--
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search