从cUrl读取PHP中的POST数据
我在
PHP中使用cUrl从一些外部服务请求.
有趣的是,服务器正在响应原始的“multipart / form-data”而不是二进制文件数据. 我的网站使用共享主机,因此PECL HTTP不是一个选项. 有没有办法用PHP解析这些数据? 示例代码: $response = curl_exec($cUrl); /* $response is raw "multipart/form-data" string --MIMEBoundaryurn_uuid_DDF2A2C71485B8C94C135176149950475371 Content-Type: application/xop+xml; charset=utf-8; type="text/xml" Content-Transfer-Encoding: binary (xml data goes here) --MIMEBoundaryurn_uuid_DDF2A2C71485B8C94C135176149950475371 Content-Type: application/zip Content-Transfer-Encoding: binary (binary file data goes here) */ 编辑:我尝试将响应传递给localhost HTTP请求,但响应数据可能超过PHP进程中允许的内存大小.扩展内存限制不是很实用,这个操作也大大降低了服务器性能. 如果没有原始问题的替代方法,您可以建议一种方法来处理非常大的POST请求,以及XML解析,就PHP中的流而言. 我知道这很难,请评论.我愿意讨论. 解决方法
如果您需要来自响应的zip文件,我想您可以只编写一个tmp文件来保存curl响应,并将其作为变通方法流式传输:
从来没有试过多部分卷发,但我想它应该工作. $fh = fopen('/tmp/foo','w'); $cUrl = curl_init('http://example.com/foo'); curl_setopt($cUrl,CURLOPT_FILE,$fh); // redirect output to filehandle curl_exec($cUrl); curl_close($cUrl); fclose($fh); // close filehandle or the file will be corrupted 如果您不需要除响应的xml部分之外的任何内容,则可能需要禁用标头 curl_setopt($cUrl,CURLOPT_HEADER,FALSE); 并添加选项以仅接受xml作为响应 curl_setopt($cUrl,CURLOPT_HTTPHEADER,array('Accept: application/xml')); //That's a workaround since there is no available curl option to do so but http allows that [编辑] 盲目猜测… $headers = array ( 'Content-Type: multipart/form-data; boundary=' . $boundary,'Content-Length: ' . strlen($requestBody),'X-EBAY-API-COMPATIBILITY-LEVEL: ' . $compatLevel,// API version 'X-EBAY-API-DEV-NAME: ' . $devID,'X-EBAY-API-APP-NAME: ' . $appID,'X-EBAY-API-CERT-NAME: ' . $certID,'X-EBAY-API-CALL-NAME: ' . $verb,'X-EBAY-API-SITEID: ' . $siteID,); $cUrl = curl_init(); curl_setopt($cUrl,CURLOPT_URL,$serverUrl); curl_setopt($cUrl,CURLOPT_TIMEOUT,30 ); curl_setopt($cUrl,CURLOPT_SSL_VERIFYPEER,0); curl_setopt($cUrl,CURLOPT_SSL_VERIFYHOST,$headers); curl_setopt($cUrl,CURLOPT_POST,1); curl_setopt($cUrl,CURLOPT_POSTFIELDS,$requestBody); curl_setopt($cUrl,CURLOPT_RETURNTRANSFER,CURLOPT_FAILONERROR,0 ); curl_setopt($cUrl,CURLOPT_FOLLOWLOCATION,1 ); curl_setopt($cUrl,CURLOPT_USERAGENT,'ebatns;xmlstyle;1.0' ); curl_setopt($cUrl,CURLOPT_HTTP_VERSION,1 ); // HTTP version must be 1.0 $response = curl_exec($cUrl); if ( !$response ) { print "curl error " . curl_errno($cUrl ) . PHP_EOL; } curl_close($cUrl); [编辑II] 这只是一个尝试,如上所述,我不能让我的卷曲页面响应多部分表单数据.所以在这里和我一起温柔;) $content_type = ""; //use last know content-type as a trigger $tmp_cnt_file = "tmp/tmpfile"; $xml_response = ""; // this will hold the "usable" curl response $hidx = 0; //header index.. counting the number of different headers received function read_header($cUrl,$string)// this will be called once for every line of each header received { global $content_type,$hidx; $length = strlen($string); if (preg_match('/Content-Type:(.*)/',$string,$match)) { $content_type = $match[1]; $hidx++; } /* should set $content_type to 'application/xop+xml; charset=utf-8; type="text/xml"' for the first and to 'application/zip' for the second response body echo "Header: $string<br />n"; */ return $length; } function read_body($cUrl,$string) { global $content_header,$xml_response,$tmp_cnt_file,$hidx; $length = strlen($string); if(stripos ( $content_type,"xml") !== false) $xml_response .= $string; elseif(stripos ($content_type,"zip") !== false) { $handle = fopen($tmp_cnt_file."-".$hidx.".zip","a"); fwrite($handle,$string); fclose($handle); } /* elseif {...} else{...} depending on your needs echo "Received $length bytes<br />n"; */ return $length; } 当然,设置适当的curlopts // Set callback function for header curl_setopt($cUrl,CURLOPT_HEADERFUNCTION,'read_header'); // Set callback function for body curl_setopt($cUrl,CURLOPT_WRITEFUNCTION,'read_body'); 不要忘记不要因为内存问题而将curl响应保存到变量中, //$response = curl_exec($cUrl); curl_exec($cUrl); 对于解析代码,您可以参考$xml_response以及在此方案中以tmp / tmpfile-2开头创建的临时文件.同样,我无法以任何方式测试上面的代码.所以这可能不起作用(但它应该是imho;)) [编辑III] 假设我们希望curl将所有传入数据直接写入另一个(传出)流,在本例中为套接字连接 我不确定它是否像这样容易: $fs = fsockopen($host,$port,$errno,$errstr); $cUrl = curl_init('http://example.com/foo'); curl_setopt($cUrl,$fs); // redirect output to sockethandle curl_exec($cUrl); curl_close($cUrl); fclose($fs); // close handle 否则我们将只需要一点技巧就可以使用我们已知的写入和头部函数 //first open the socket (before initiating curl) $fs = fsockopen($host,$errstr); // now for the new callback function function socket_pipe($cUrl,$string) { global $fs; $length = strlen($string); fputs($fs,$string); // add NOTHING to the received line just send it to $fs; that was easy wasn't it? return $length; } // and of course for the CURLOPT part // Set callback function for header curl_setopt($cUrl,'socket_pipe'); // Set the same callback function for body curl_setopt($cUrl,'socket_pipe'); // do not forget to fclose($fs); //when we're done 问题是,不编辑结果并简单地将其连接到$fs将使得apache正在监听某个端口,然后您将脚本分配给该端口. fputs($fp,"POST $path HTTP/1.0n"); //where path is your script of course (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |