【问题标题】:PHP cURL doesn't set content-length properlyPHP cURL 没有正确设置内容长度
【发布时间】:2016-03-17 22:57:57
【问题描述】:

我正在尝试通过 cURL 上传文件,但缺少某些内容。我强制此请求为 HTTP 1.0,因为如果我使用 HTTP 1.1,cURL 会添加 Expect: 100 标头,这就是额外标头的原因。下面是一个简单的测试代码:

<?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;
}
?>

我基于 Jersey 的服务器获取了它,我可以看到这些标题:

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

看到内容长度了吗?太短了当我通过我的 Postman REST 客户端发送相同的文件和相同的请求时,我得到了这些标头:

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

内容长度现在是设置属性。这里有什么问题?

【问题讨论】:

  • 在我看来您只是在发送文件名,而不是文件内容....这样就可以解释内容长度差异
  • 嗯,我发现的大多数消息来源都说这就是您需要发送文件的方式。例如:stackoverflow.com/questions/21905942/…
  • 您使用的是什么版本的 PHP? 5.6.0 更改了默认上传文件的方式。

标签: php curl file-upload multipartform-data


【解决方案1】:

听起来您使用的是 PHP 5.6.0 或更高版本。在此版本中,默认情况下禁用文件上传的 @ 前缀。您可以使用

curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);

此选项是在 5.5 中添加的,但默认为 false 以实现向后兼容; 5.6 更改默认不兼容。

从 5.5 开始执行文件上传的首选方法是使用 CurlFile 类。

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

【讨论】:

  • 谢谢,确实是这个问题。
【解决方案2】:

您必须实际插入文件内容,这与 curl 的 cli 版本不同。 试试:

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

【讨论】:

  • 请看我上面的评论
  • 我不认为这会将它作为文件上传发送,这会将文件内容作为原始数据发送。
  • 除了传输原始文件内容之外,什么是“文件上传”?据我从问题中可以看出,文件内容应在名为“文件”的后字段中传输。首先,我试图解释内容长度的差异
  • 上传文件时,会发送额外的标头以及文件的详细信息,例如其 MIME 类型。
  • 你不知道,如果询问者试图以这种方式封装数据。据我解释,他试图模仿 curl-cli-version 中的 @-Operator。这正是我的示例所做的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-07
  • 2013-08-06
  • 2012-03-25
  • 2012-05-01
相关资源
最近更新 更多