4

I need to recreate this in PHP:

curl -X POST --user <username>:<password>
--header "Content-Type: text/plain;charset=utf-8"
--header "Accept: application/json"
--data-binary @<filename>
"https://gateway.watsonplatform.net/personality-insights/api/v3/profile"

I've got this:

$request_headers = array();
$request_headers[] = 'Content-Type: text/plain;charset=utf-8';
$request_headers[] = 'Content-Language: en';
$request_headers[] = 'Accept-Language: en';

$simple_data = 'washingtonpost by the intelligence community';
    curl_setopt_array( $ch2, array(
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => $simple_data,
        CURLOPT_HEADER => $request_headers,
        CURLOPT_USERPWD => 'XXXX:YYYY',
    )
    );
    $response2 = curl_exec( $ch2 );

What my code doesn't account for is the --data-binary part, but I'm not sure how to "translate" this into PHP. In addition, can I use data binary with plain text (the API accepts it) instead of JSON?

2
  • 1
    In your code, CURLOPT_HEADER should be CURLOPT_HTTPHEADER to set request headers. Otherwise, POSTFIELDS is correct as is with the custom Content-Type. Commented Feb 21, 2017 at 4:45
  • @drew010 This was exactly the problem! Thank you! If you submit as an answer, I can accept. Appreciate it. Commented Feb 21, 2017 at 12:19

3 Answers 3

2

What you have is already a --data-binary equivalent. See the CURLOPT_POSTFIELDS API docs:

You must make sure that the data is formatted the way you want the server to receive it. libcurl will not convert or encode it for you in any way.

Compare that to the docs for the command-line --data-binary option:

This posts data exactly as specified with no extra processing whatsoever.

As far as the second part of your question:

can I use data binary with plain text (the API accepts it) instead of JSON

Yeah, both for --data-binary from the command line and CURLOPT_POSTFIELDS from the API.

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

4 Comments

Thanks...this is giving me 415 Unsupported Media Type errors that I can't track down given the very simple string I'm trying to send in this example.
I would think that 415 Unsupported Media Type is just the service looking at the Content-Type: text/plain header and saying it doesn’t support that (though why I dunno since your question indicates it should). I guess changing that to application/json and trying again would be the thing to do (if you’ve not already). But anyway as far as I can see, that 415 isn’t being caused by any malformedness in what your libcurl code is sending.
I'm running the exact same thing using the CLI and it works perfectly fine. Is there something that's being changed (or not changed) in the translation that I'm missing?
I think the problem is just what’s mentioned by in the comment above at stackoverflow.com/questions/42358104/… That is, you need CURLOPT_HTTPHEADER instead of CURLOPT_HEADER.
2

Ok, I've found a way to stream the 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

0

If you set the value of CURLOPT_POSTFIELDS as an array (which if you use CURLFile it will be), the post will be formatted as multipart, breaking the data-binary part.

I did not find a way to use CURLFile wihtout the multipart/form-data side effect...

What I use is this, but it uses file_get_contents which is not very memory friendly (it will load the entire file in memory):

    <?php

    $file_local_full = '/tmp/foobar.png';

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

    // if the file is too big, it should be streamed
    $curl_opts = array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => "POST",
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_POSTFIELDS => file_get_contents($file_local_full),
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1
    );
    // echo "curl_opts:\n" . print_r($curl_opts, true) . "\n"; exit;

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

    $response = curl_exec($curl);

Comments

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.