17

I'm using an API that wants me to send a POST with the binary data from a file as the body of the request. How can I accomplish this using PHP cURL?

The command line equivalent of what I'm trying to achieve is:

curl --request POST --data-binary "@myimage.jpg" https://myapiurl
1

6 Answers 6

41

You can just set your body in CURLOPT_POSTFIELDS.

Example:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,            "http://url/url/url" );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($ch, CURLOPT_POST,           1 );
curl_setopt($ch, CURLOPT_POSTFIELDS,     "body goes here" ); 
curl_setopt($ch, CURLOPT_HTTPHEADER,     array('Content-Type: text/plain')); 

$result=curl_exec ($ch);

Taken from here

Of course, set your own header type, and just do file_get_contents('/path/to/file') for body.

Sign up to request clarification or add additional context in comments.

5 Comments

That was a life saver. I was trying to send a file in postfields in few ways, didn't think of this one!
That do help! Seems this method can upload any kind of files with header "Content-Type: application/binary".
@Neptune Sure, but setting correct Content-Type makes sure receiving end can correctly determine data type.
No need to add @ before file path.
Of course, set your own header type, and just do file_get_contents('/path/to/file') for body. This is most impotrtant
5

to set body to binary data and upload without multipart/form-data, the key is to cheat curl, first we tell him to PUT, then to POST:

    <?php
    
    $file_local_full = '/tmp/foobar.png';
    $content_type = mime_content_type($file_local_full);

    $headers = array(
        "Content-Type: $content_type", // or whatever you want
    );

    $filesize = filesize($file_local_full);
    $stream = fopen($file_local_full, 'r');

    $curl_opts = array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_PUT => true,
        CURLOPT_CUSTOMREQUEST => "POST",
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_INFILE => $stream,
        CURLOPT_INFILESIZE => $filesize,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1
    );

    $curl = curl_init();
    curl_setopt_array($curl, $curl_opts);

    $response = curl_exec($curl);

    fclose($stream);

    if (curl_errno($curl)) {
        $error_msg = curl_error($curl);
        throw new \Exception($error_msg);
    }

    curl_close($curl);

credits: How to POST a large amount of data within PHP curl without memory overhead?

Comments

2

This can be done through CURLFile instance:

$uploadFilePath = __DIR__ . '/resource/file.txt';

if (!file_exists($uploadFilePath)) {
    throw new Exception('File not found: ' . $uploadFilePath);
}

$uploadFileMimeType = mime_content_type($uploadFilePath);
$uploadFilePostKey = 'file';

$uploadFile = new CURLFile(
    $uploadFilePath,
    $uploadFileMimeType,
    $uploadFilePostKey
);

$curlHandler = curl_init();

curl_setopt_array($curlHandler, [
    CURLOPT_URL => 'https://postman-echo.com/post',
    CURLOPT_RETURNTRANSFER => true,

    /**
     * Specify POST method
     */
    CURLOPT_POST => true,

    /**
     * Specify array of form fields
     */
    CURLOPT_POSTFIELDS => [
        $uploadFilePostKey => $uploadFile,
    ],
]);

$response = curl_exec($curlHandler);

curl_close($curlHandler);

echo($response);

See - https://github.com/andriichuk/php-curl-cookbook#upload-file

1 Comment

Won't this result in a multipart request?
0

Try this:

$postfields = array(
    'upload_file' => '@'.$tmpFile
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url.'/instances');
curl_setopt($ch, CURLOPT_POST, 1 );
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);//require php 5.6^
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$postResult = curl_exec($ch);

if (curl_errno($ch)) {
    print curl_error($ch);
}
curl_close($ch); 

Comments

0

Below solution worked fine for me.

$ch = curl_init();

$post_url = "https://api_url/"
curl_setopt($ch, CURLOPT_URL, $post_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');

$post = array(
            'file' => '@' .realpath('PATH_TO_DOWNLOADED_ZIP_FILE')
         );
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

$headers = array();
$headers[] = 'Authorization: Bearer YOUR_ACCESS_TOKEN';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

refered: curl to php-curl

Comments

-2

You need to provide appropriate header to send a POST with the binary data.

$header = array('Content-Type: multipart/form-data');
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($resource, CURLOPT_POSTFIELDS, $arr_containing_file);

Your $arr_containing_file can for example contain file as expected (I mean, you need to provide appropriate expected field by the API service).

$arr_containing_file = array('datafile' => '@inputfile.ext');

2 Comments

Doesn't this result in a multipart/form-data style POST? Because I need the body to only contain the image data.
I have updated my question with a command line equivalent of my goal.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.