1

How can I "correctly" upload the content of a file with cURL?

There are a lot of explanations and questions here where tmp files are send by curl with a @prefix on the file or using the curlFile api. In My use case I don't want to create a tmp file, and just post the content of file_get_contents('php://input') as body of the post request. The server does not accept multipart form requests.

The Following snipped will work in PHP7:

$body = file_get_contents('php://input'); $ch = curl_init(); curl_setopt($ch, CURLOPT_POSTFIELDS, $body); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); 

It feels ugly to set the content type to json, no matter what the actual content of the stream may holds. But it seems to work. Sadly I need to support a really old version of PHP and feel like running out of options.

My question is: Is the above example correct, even for PHP 7 or can it be made better? Additionally: Is there any improvement or option that can be used to make this work with PHP 5.3.10? In this old version the post body always seems to be empty.

1 Answer 1

2

Finally I found and answer on this blog

Adding curl_setopt($curl, CURLOPT_POSTREDIR, 3); was the required option to acutally make the post request work without having an empty body.


Edit & heads up: This option is only needed when you expect your request to be redirected. I made a mistake while asking this question and posting the answer. Please check if your requests is redirected form http to https or the other way around and fix this first to prevent problems.


Copied from blog post of Evert Pot, linked above:

Using CURLOPT_POSTFIELDS you can supply a request body as a string. Lets try to upload our earlier failed request using that method:

<?php $curl = curl_init('http://example.org/someredirect'); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($curl, CURLOPT_POSTFIELDS, file_get_contents('largefile.json')); curl_exec($curl); ?> 

This also will not work exactly as you expect. While the second request to /someredirect will still be a POST request, it will be sent with an empty request body.

To fix this, use the undocumented CURLOPT_POSTREDIR option.

<?php $curl = curl_init('http://example.org/someredirect'); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($curl, CURLOPT_POSTFIELDS, file_get_contents('largefile.json')); curl_setopt($curl, CURLOPT_POSTREDIR, 3); curl_exec($curl); ?> 

According to the PHP changelog, this was added in PHP 5.3.2, and according to PHP bug #49571 there are four possible values:

0 -> do not set any behavior 1 -> follow redirect with the same type of request only for 301 redirects. 2 -> follow redirect with the same type of request only for 302 redirects. 3 -> follow redirect with the same type of request both for 301 and 302 redirects.

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.