breakline
breakline

Reputation: 6073

PHP cURL doesn't set content-length properly

I'm trying to upload a file via cURL but something is missing. I forces this request to be HTTP 1.0 because cURL adds the Expect: 100 header if I use HTTP 1.1 so thats why the extra header. Here is a simple test code:

<?php
if(isset($_POST["id"])) {
  $data = array("id" => $_POST["id"]);
  $data["file"] = "@".realpath($_FILES["file"]["tmp_name"]);
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Authorization: Bearer 0e39ffba-66cd-4933-9e94-fcdf600c2453',
    'Connection: keep-alive'
  ));
  curl_setopt($ch, CURLOPT_URL, "http://localhost:8080/test-api/upload");
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  curl_setopt($ch, CURLOPT_VERBOSE, false);
  curl_setopt($ch, CURLOPT_HTTP_VERSION, 1);
  $response = curl_exec($ch);
  var_dump($response);
  exit;
}
?>

My Jersey based server picks it up, and I can see these headers:

INFO: 25 * Server has received a request on thread http-nio-8080-exec-1
25 > POST http://localhost:8080/test-api/upload
25 > authorization: Bearer 0e39ffba-66cd-4933-9e94-fcdf600c2453
25 > connection: keep-alive
25 > content-length: 261
25 > content-type: multipart/form-data; boundary=------------------------53f7ba34739b4d9e
25 > host: localhost:8080

See the content-length? It's way too short. When I send the same file and the same request via my Postman REST client, I get these headers:

INFO: 26 * Server has received a request on thread http-nio-8080-exec-3
26 > POST http://localhost:8080/test-api/upload
26 > accept-encoding: gzip, deflate
26 > accept-language: hu-HU,hu;q=0.8,en-US;q=0.6,en;q=0.4
26 > authorization: Bearer 0e39ffba-66cd-4933-9e94-fcdf600c2453
26 > cache-control: no-cache, no-cache
26 > connection: keep-alive
26 > content-length: 144954
26 > content-type: multipart/form-data; boundary=----WebKitFormBoundarye5Tg0kEqi10nEBwv
26 > cookie: ff_uvid=126143952; _ga=GA1.1.459454356.1439469592; CAKEPHP=9mffidqo8203ugktan4roc0u82
26 > host: localhost:8080
26 > origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
26 > user-agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36

The content-length now is set property. What could be wrong here?

Upvotes: 0

Views: 2124

Answers (2)

Barmar
Barmar

Reputation: 780842

It sounds like you're using PHP 5.6.0 or later. As of this release, the @ prefix for file uploads is disabled by default. You can enable it with

curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);

This option was added in 5.5, but the default was false for backward compatibility; 5.6 changed the default incompatibly.

The preferred way to perform file uploads starting with 5.5 is with the CurlFile class.

$data["file"] = new CurlFile(realpath($_FILES["file"]["tmp_name"]));

Upvotes: 2

Ctx
Ctx

Reputation: 18420

You have to actually insert the filecontent, this differs from the cli-version of curl. try:

  $data["file"] = file_get_contents($_FILES["file"]["tmp_name"]);

Upvotes: 0

Related Questions