Zend_Http_Client - 为啥我的 POST 请求发送错误的内容类型标头?

Posted

技术标签:

【中文标题】Zend_Http_Client - 为啥我的 POST 请求发送错误的内容类型标头?【英文标题】:Zend_Http_Client - Why does my POST request send the wrong content-type header?Zend_Http_Client - 为什么我的 POST 请求发送错误的内容类型标头? 【发布时间】:2012-06-01 08:03:27 【问题描述】:

我正在使用 Zend Http 客户端调用外部服务。该服务允许我将文件上传到他们的存储系统。它需要在查询字符串中发送相关参数(用户 ID 等),并且文件上传内容应在 POST 正文中发送,内容类型为“application/zip”(我发送的是 zip 文件里面有各种各样的东西)。

为此,我使用 zend 客户端的 setParameterGet() 函数在查询字符串中设置参数。然后我使用 setFileUpload() 函数设置文件上传内容:

$this->client->setFileUpload($zipFilePath, 'content', null, 'application/zip');

但是,服务告诉我我发送的内容类型错误,即“multipart/form-data”

这是 Zend 客户端发送给服务的原始标头(请注意,我已经删除了一些敏感信息,用 [] 括号括起来的项目名称替换它们)

发布 https://[ServiceURL]?cmd=[COMMAND]&enrollmentid=[ENROLLMENTID]&itemid=[ITEMID]

HTTP/1.1

主机:[HOST] 接受编码:gzip、deflate

用户代理:Zend_Http_Client Cookie:

AZT=9cMFAIBgG-eM1K|Bw7Qxlw7pBuPJwm0PCHryD;

内容类型:multipart/form-data;边界=---ZENDHTTPCLIENT-05535ba63b5130ab41d9c75859f678d8

内容长度:2967

-----ZENDHTTPCLIENT-05535ba63b5130ab41d9c75859f678d8

内容配置:表单数据;名称=“内容”; 文件名="agilixContent.zip"

内容类型:应用程序/zip

[此处为原始文件数据]

所以基本上,即使我设置了 POST 内容类型标头,我的外部服务仍然告诉我我发送了错误的内容类型,因为还有另一个值为“multipart/form-data”的内容类型标头”。我尝试更改/删除该内容标题,但无济于事。 如何删除该标头,以便我的请求中不会有这两个重复的“内容类型”标头?

【问题讨论】:

我正在查看 HTTP_Client (framework.zend.com/apidoc/1.11) 的 ZF API,您是否尝试过使用“setEncType(string $enctype)”,setFileUpload 的 API 是:“setFileUpload(string $filename, string $formname, string $data = null, string $ctype = null )",我必须做一些挖掘,但它可能不是实际设置整体标头编码的原因。我正在研究参考指南,看看那里是否有任何帮助。 我只是在发出请求之前尝试使用 setEncType('application/zip'),但标题似乎没有改变。第一个仍然说“multipart/form-data”,而第二个说“application/zip”。感谢您的建议,我还没有想过尝试该功能。 :) 嗯...我正在深入研究 ZF 代码 (Zend/Http/Client.php),我正在查找 multipart/form-data 并看到此评论 Force enctype to multipart/form-data对于setFileUpload() 函数。这包括_prepareBody()If we have files to upload, force enctype to multipart/form-data。长话短说,ZF_Http_Client 似乎不允许您将整体数据包内容类型设置为application/zip。 i 可能有一个很好的理由,但这可能是因为 zip 是一个附件,而不仅仅是一个文件。 如果你想重写它,创建一个新类并扩展客户端类并重写那段代码以允许。不过,我不得不声明,我不确定这是否是一个好建议,因为我对 HTTP 协议不够熟悉。 感谢您了解客户端在使用 setFileUpload 时强制使用 multipart/form-data!我做了一些测试,结果证明这是我的问题。我没有使用 setFileUpload,而是尝试使用 setHeaders('Content-Type', 'application/zip') 和 setRawData() 来发送 zip 文件内容,并且“multipart/form-data”标头不再随请求一起发送.该服务现在可以正常使用该更改。非常感谢! 【参考方案1】:

如果您想使用“application/zip”作为内容类型上传文件,则不应使用->setFileUpload(),而应使用->setRawData()setFileUpload() 用于模仿基于 html 表单的文件上传,这 不是 您需要的。

请参阅http://framework.zend.com/manual/en/zend.http.client.advanced.html#zend.http.client.raw_post_data 了解更多信息。您需要的(基于您的原始示例)将类似于:

$zipFileData = file_get_contents($zipFilePath);
$this->client->setRawData($zipFileData, 'application/zip');
$response = $this->client->request('POST');

请注意,如果您的 ZIP 文件可能非常大(例如超过几兆字节),您可能需要使用 ZHC 的流媒体支持功能,因此请避免占用内存。如果您知道您的文件总是小于 5-10 兆字节,我不会为此烦恼。

【讨论】:

是的,原来是这个问题。 :) 我没有意识到 setFileUpload 是在模仿上传表单字段。 setRawData 做得很好。【参考方案2】:

我不确定如何使用 Zend HTTP Client 来做到这一点,但我相信你可以使用纯 cURL 来做到这一点。您一定知道 cURL 为您提供了很大的灵活性,我还没有深入研究 Zend,但 Zend 可能会在内部使用 cURL。

<?php

// URL on which we have to post data
$url = "http://localhost/tutorials/post.php";
// Any other field you might want to catch
$post_data = "khan";
// File you want to upload/post
//$post_data['zip_file'] = "@c:/foobar.zip";

$headers[] = "Content-Type: application/zip";

// Initialize cURL
$ch = curl_init();
// Set URL on which you want to post the Form and/or data
curl_setopt($ch, CURLOPT_URL, $url);
// Data+Files to be posted
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
// Set any custom header you may want to set or override defaults
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
// Pass TRUE or 1 if you want to wait for and catch the response against the request made
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// For Debug mode; shows up any error encountered during the operation
curl_setopt($ch, CURLOPT_VERBOSE, 1);
// Execute the request
$response = curl_exec($ch);

// Just for debug: to see response
echo $response;

我希望上面的 sn-p 对你有用。这是我下面提到的博客文章中的一些修改代码。

参考:http://blogs.digitss.com/php/curl-php/posting-or-uploading-files-using-curl-with-php/

【讨论】:

fyi,我确实在本地机器上测试了上面的代码,并且按预期得到了正确的 Content-Type 标头。

以上是关于Zend_Http_Client - 为啥我的 POST 请求发送错误的内容类型标头?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的背景颜色没有显示在 <p> 上? [复制]

为啥 ryzen 上的 p-state 状态 MSR 没有改变?

React/CSS:为啥我的 <p> 标签在移动设备上移动它的父 <div>?

为啥 BeautifulSoup 将 <html><body><p> 添加到我的结果中?

为啥 ++(*p) 会改变指针值?

为啥 OPTIND 会弄乱我的位置参数?