PHP curl将内容类型更改为application/x-www-form-urlencoded。不应该';不要那样做

PHP curl将内容类型更改为application/x-www-form-urlencoded。不应该';不要那样做,php,curl,http-headers,Php,Curl,Http Headers,我想从我正在使用PHP curl的服务器上直接上传一个视频到Youtube 我需要此请求格式: POST /feeds/api/users/default/uploads HTTP/1.1 Host: uploads.gdata.youtube.com Authorization: Bearer ACCESS_TOKEN GData-Version: 2 X-GData-Key: key=adf15ee97731bca89da876c...a8dc Slug: video-test.mp4 Co

我想从我正在使用PHP curl的服务器上直接上传一个视频到Youtube

我需要此请求格式:

POST /feeds/api/users/default/uploads HTTP/1.1
Host: uploads.gdata.youtube.com
Authorization: Bearer ACCESS_TOKEN
GData-Version: 2
X-GData-Key: key=adf15ee97731bca89da876c...a8dc
Slug: video-test.mp4
Content-Type: multipart/related; boundary="f93dcbA3"
Content-Length: 1941255
Connection: close

--f93dcbA3
Content-Type: application/atom+xml; charset=UTF-8

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom"
  xmlns:media="http://search.yahoo.com/mrss/"
  xmlns:yt="http://gdata.youtube.com/schemas/2007">
  <media:group>
    <media:title type="plain">Bad Wedding Toast</media:title>
    <media:description type="plain">
      I gave a bad toast at my friend's wedding.
    </media:description>
    <media:category
      scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People
    </media:category>
    <media:keywords>toast, wedding</media:keywords>
  </media:group>
</entry>
--f93dcbA3
Content-Type: video/mp4
Content-Transfer-Encoding: binary

<Binary File Data>
--f93dcbA3--
转储结果显示curl将
内容类型
更改为
应用程序/x-www-form-urlencoded
,这当然是youtube不支持的

我将我的二进制内容(视频)放入
CURLOPT_POSTFIELDS
,也许这是错误的,但我不知道如何设置除此之外的请求主体

那么如何保留我设置的内容类型呢?

根据设置,HTTP方法设置为
POST
默认为内容类型设置为
application/x-www-form-urlencoded
。因此,我怀疑一次设置所有选项会导致您的
内容类型被覆盖。
我的建议是在设置方法之后,在单个语句中设置内容类型,即

$curlConfig = array(
    CURLOPT_URL => 'http://uploads.gdata.youtube.com/feeds/api/users/default/uploads',
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_BINARYTRANSFER => true,
    CURLOPT_POSTFIELDS => $content,
);

curl_setopt_array($ch, $curlConfig);

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Authorization: ' . sprintf('GoogleLogin auth=%s', $this->accessToken),
    'GData-Version: 2',
    'X-GData-Key: ' . sprintf('key=%s', $this->developerKey),
    'Slug: ' . sprintf('%s', $this->video->getFilename()),
    'Content-Type: ' . sprintf('multipart/related; boundary="%s"',
                                  $this->boundaryString),
    'Content-Length: ' . strlen($content),
    'Connection: close'
));

接受的答案对我没有帮助,我在你的代码中发现了另一个问题。根据当前的PHP设置,HTTPHEADER必须如下设置:

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-type: text/plain',
    'Content-length: 100'
));
它必须是字符串列表,而不是类似于
数组('Content-Type'=>'text/plain')
的散列。
希望它能节省一些人的调试时间。

根据文档
CURLOPT_POST
内容类型自动设置为
application/x-www-form-urlencoded
。可以尝试在单个语句中设置此选项和
CURLOPT\u标题
,或者在设置方法后,使用
curl\u setopt
在单个语句中至少设置后者。你能把这个作为一个答案发布给我吗?换句话说,你不能把一个关联数组传递给CURLOPT_HTTPHEADER,只能传递简单数组。这个问题让我疯狂了好几个小时…请更新你的例子,它不是二维数组。它应该是:数组(“授权:.sprintf…,”内容类型:.sprintf…)@JohnCongdon:正确,谢谢!有趣的是,在短短两年多的时间里,没有人注意到这一点,三次投票和“接受答案”。(我敢肯定你的意思是“不是关联数组”而不是“不是二维数组”))为PHP旋度感到羞耻。不仅
CURLOPT_POST
覆盖
内容类型
,而且防止同时设置其他HTTP头。谢谢你的解决方案!我无法让这个解决方案起作用。我已经将标题的设置与其他选项分开,它仍然添加了额外的内容类型。@dmarra我建议只使用专用的客户端库,例如GuzzleHttp
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-type: text/plain',
    'Content-length: 100'
));