200分求助CURL设置HTTPHEADER上传文件问题! curl不支持这种方式,你需要自己构造数据包。我研究过 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 http://cn.php.net/fsockopenCTRL + F搜索boundary,例子好好看看,构建一个文件上传的http请求头即可,按理说CURL构建同样的请求头应该也没问题。 总结一下项目中用到curl的几种方式 1. php curl的默认调用方法,get方式访问url Java代码 .... $ch = curl_init(); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //设置http头 curl_setopt($ch, CURLOPT_ENCODING, "gzip" ); //设置为客户端支持gzip压缩 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30 ); //设置连接等待时间 curl_setopt($ch, CURLOPT_URL, $url ); curl_exec( $ch ); if ($error = curl_error($ch) ) { //出错处理 return -1; } fclose($fp); $curl_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //获取http返回值 if( $curl_code == 200 ) { //正常访问url } //异常 .... .... $ch = curl_init(); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //设置http头 curl_setopt($ch, CURLOPT_ENCODING, "gzip" ); //设置为客户端支持gzip压缩 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30 ); //设置连接等待时间 curl_setopt($ch, CURLOPT_URL, $url ); curl_exec( $ch ); if ($error = curl_error($ch) ) { //出错处理 return -1; } fclose($fp); $curl_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //获取http返回值 if( $curl_code == 200 ) { //正常访问url } //异常....2. 设置http header支持curl访问lighttpd服务器 Java代码 $header[]= 'Expect:'; $header[]= 'Expect:'; 3. 设置curl,只获取http header,不获取body: Java代码 curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_NOBODY, 1); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_NOBODY, 1); 或者只获取body: Java代码 curl_setopt($ch, CURLOPT_HEADER, 0); // make sure we get the body curl_setopt($ch, CURLOPT_NOBODY, 0); curl_setopt($ch, CURLOPT_HEADER, 0); // make sure we get the body curl_setopt($ch, CURLOPT_NOBODY, 0); 4. 访问虚拟主机,需设置Host $header[]= 'Host: '.$host; 5. 使用post, put, delete等REStful方式访问url post: curl_setopt($ch, CURLOPT_POST, 1 ); put, delete: curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE"); //或者PUT,需要服务器支持这些方法。 6. 保存下载内容为文件 curl_setopt($ch, CURLOPT_FILE, $fp); 貌似没看到使用了CURLOPT_HTTPHEADER 谢谢,CURL不支持这种上传方法吗? 可能是比较复杂吧,所以 curl 提供了 '@'.文件名 的方式。把构造头和数据的工作留给了自己但 curl 依然提供了 CURLOPT_UPLOAD 来表示上传文件,但实际上使用了 PUT 请求只适合向 ftp 上传文件在 php 中,要从 php://input 读取使用 #5 给出的代码,会产生 无法识别的请求 这样的错误,注释掉文件上传的那段,依然报这个错。不知是什么原因但对比 curl PUT 方式的数据报,似乎也没有什么差异 知道了,这样写就可以!$contents =<<< 'TEXT'数据报中应该是Content-Disposition: form-data; name="userfile"; filename="file_name"Content-Type: 文档类型文件内容这样的格式,我只实现了文件名部分,文档类型不知道如何实现。这样上传后就取不到 type 的值curl_upload_server.php<xmp><?phpprint_r($_FILES);echo "文件内容:\n";$p = current($_FILES);readfile($p['tmp_name']);TEXT;$fields['f"; filename="x.x'] = $contents; //这个关联键的写法很怪异吧?$ch = curl_init(); curl_setopt($ch, CURLOPT_URL,"http://localhost/curl_upload_server.php"); curl_setopt($ch, CURLOPT_POST, 1 );curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);$s = curl_exec ($ch); curl_close ($ch); echo $s; 原来这样就有 type了$varname = 'my';$name = '3.txt';$type = 'text/plain';$key = <<< TEXT$varname"; filename="$nameContent-Type: $typeTEXT;$fields[$key] = $contents;注意:我是在 win 下的,linux 下要将 \n 换成 \r\n没办法,早年的 sun 是拼不过 ms 的,现在也不行吧?一直以为上传的文件类型是 php 识别的,却原来是浏览器提供的 很感谢,有没有比较完整的CURL 通过拼接HTTPHEADER信息上传的POST示例呢? #10 就是curl_upload_server.php 就是测试用服务器端<xmp><?phpprint_r($_FILES);echo "文件内容:\n";$p = current($_FILES);readfile($p['tmp_name']); 本帖最后由 xuzuning 于 2012-04-10 13:19:42 编辑 http文件上传协议,主要是那个boundary,这个东西就是标识一个文件的内容和类型以及各种上传参数的token,其它和普通的POST提交也没啥区别。fsockopen来写http请求就比较直白,用curl的话模拟对应的请求头和body就好了。<?php//what file you want to upload$uploadFile = file_get_contents("/var/www/index.html");//content boundary $boundary = md5(time());$postStr = "";$postStr .="--".$boundary."\r\n";$postStr .="Content-Disposition: form-data; name=\"uptxt\"; filename=\"index.html\"\r\n";$postStr .="Content-Type: text/html\r\n\r\n";$postStr .=$uploadFile."\r\n";$postStr .="--".$boundary."\r\n"; /** use fsockopen to set upload http header and body **/$fp = fsockopen("localhost","80",$errer,$errno,1);fwrite($fp,"POST /upload.php HTTP/1.0\r\n");fwrite($fp,"Content-Type: multipart/form-data; boundary=".$boundary."\r\n");fwrite($fp,"Content-length:".strlen($postStr)."\r\n\r\n");fwrite($fp,$postStr);while (!feof($fp)){ echo fgets($fp, 128);}fclose($fp);/** use curl instead **/$cl = curl_init('http://localhost/upload.php');$boundary = md5(time());curl_setopt($cl,CURLOPT_POST,true);curl_setopt($cl,CURLOPT_HTTPHEADER,array( "Content-Type: multipart/form-data; boundary=".$boundary));curl_setopt($cl,CURLOPT_POSTFIELDS,$postStr);curl_setopt($cl,CURLOPT_RETURNTRANSFER,true);$content = curl_exec($cl);curl_close($cl);echo $content;?>upload.php<?php print_r($_FILES);?>结果HTTP/1.1 200 OKServer: nginx/0.8.54Date: Tue, 10 Apr 2012 05:22:01 GMTContent-Type: text/htmlConnection: closeX-Powered-By: PHP/5.3.10Array( [uptxt] => Array ( [name] => index.html [type] => text/html [tmp_name] => /tmp/phpKHfxkY [error] => 0 [size] => 344 ))Array( [uptxt] => Array ( [name] => index.html [type] => text/html [tmp_name] => /tmp/phpB0se13 [error] => 0 [size] => 344 )) 非常感谢,CURL部分的代码我这边测试成功了,我再加一百分 #14 服务器端#15 客户端#14 中的 $contents 是待上传的文件内容 上次好像看到你问的是一个文件切分多份,然后上传,如果是这样的话,你要要做的只是用boundary标识多个上传内容区块。比如$boundary = md5(time());$postStr = "";$postStr .="--".$boundary."\r\n";$postStr .="Content-Disposition: form-data; name=\"uptxt[]\"; filename=\"index_1.html\"\r\n";$postStr .="Content-Type: text/html\r\n\r\n";$postStr .=$uploadFile."\r\n"; #这里是部分文件内容$postStr .="--".$boundary."\r\n";$postStr .="--".$boundary."\r\n";$postStr .="Content-Disposition: form-data; name=\"uptxt[]\"; filename=\"index_2.html\"\r\n"; $postStr .="Content-Type: text/html\r\n\r\n";$postStr .=$uploadFile."\r\n";#这里是部分文件内容$postStr .="--".$boundary."\r\n"; to #21你这样做是不行的,应该使用 curl_multi 并发不然把一个文件拆成几个,一次性传出,再在服务器端组装。有什么意义? 说的也是哈,不过curl_multi的并发,对于请求不同的url后获取数据比较有意义,就是说是并行请求不同的url获取http返回。如果往同一url请求,要么就一次请求,要么就分发多次请求,多次请求有个性能消耗在于每次都要scoket连接/销毁,但是能控制请求字节数。 忘了如果服务器支持keep-alive的话,无需进行多次socket create,呵呵 嗯,基本上都支持keep-alive了 CSDN的编辑器还是没改进,同时回复多个还需要手动复制代码 照着PHP手册里去做反而没成功 是吗?你不如用wireshark,smartsniff等工具查看http请求格式(firebug或者chrome自带的F12应该也可以),执行一次上传文件动作,然后观察文件上传时的http请求格式。 贴个post的socket代码:我测试过的备份!http://webinno.cn/blog/article/view/40 CURLOPT_HEADERFUNCTION这个参数可以设置HTTP协议回调,你可以参考下 curl只要你设置些参数,然后他自己会生成协议头提交服务器 请问怎么奖XML传来的数据去MYSQL数据库查询出来! mysql 修改字段问题 EclipsePHP 怎么折叠自定义的代码 apache 配置二级域名问题~~郁闷中 header 下载,文件末尾多了个问号? 【一起混吧】 正则挑战下 来战吧!!!! 经常忘掉函数参数位置 高分求助 自愿!!分多者进! 高手请看啊,这事真是难做 curl多线程采集不是采集不到就是采不全? 请问如何解压.tar.gz .gzip .gz 类型文档
CTRL + F搜索boundary,例子好好看看,构建一个文件上传的http请求头即可,按理说CURL构建同样的请求头应该也没问题。
1. php curl的默认调用方法,get方式访问url
Java代码
....
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //设置http头
curl_setopt($ch, CURLOPT_ENCODING, "gzip" ); //设置为客户端支持gzip压缩
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30 ); //设置连接等待时间
curl_setopt($ch, CURLOPT_URL, $url );
curl_exec( $ch );
if ($error = curl_error($ch) ) {
//出错处理
return -1;
}
fclose($fp);
$curl_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //获取http返回值
if( $curl_code == 200 ) {
//正常访问url
}
//异常
.... ....
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //设置http头
curl_setopt($ch, CURLOPT_ENCODING, "gzip" ); //设置为客户端支持gzip压缩
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30 ); //设置连接等待时间
curl_setopt($ch, CURLOPT_URL, $url );
curl_exec( $ch );
if ($error = curl_error($ch) ) {
//出错处理
return -1;
}
fclose($fp); $curl_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //获取http返回值
if( $curl_code == 200 ) {
//正常访问url
}
//异常
....
2. 设置http header支持curl访问lighttpd服务器
Java代码
$header[]= 'Expect:'; $header[]= 'Expect:';
3. 设置curl,只获取http header,不获取body:
Java代码
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1); curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
或者只获取body:
Java代码
curl_setopt($ch, CURLOPT_HEADER, 0); // make sure we get the body
curl_setopt($ch, CURLOPT_NOBODY, 0); curl_setopt($ch, CURLOPT_HEADER, 0); // make sure we get the body
curl_setopt($ch, CURLOPT_NOBODY, 0);
4. 访问虚拟主机,需设置Host
$header[]= 'Host: '.$host;
5. 使用post, put, delete等REStful方式访问url
post:
curl_setopt($ch, CURLOPT_POST, 1 );
put, delete:
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE"); //或者PUT,需要服务器支持这些方法。
6. 保存下载内容为文件
curl_setopt($ch, CURLOPT_FILE, $fp);
貌似没看到使用了CURLOPT_HTTPHEADER
谢谢,CURL不支持这种上传方法吗?
只适合向 ftp 上传文件
在 php 中,要从 php://input 读取使用 #5 给出的代码,会产生 无法识别的请求 这样的错误,注释掉文件上传的那段,依然报这个错。不知是什么原因
但对比 curl PUT 方式的数据报,似乎也没有什么差异
数据报中应该是
Content-Disposition: form-data; name="userfile"; filename="file_name"
Content-Type: 文档类型文件内容这样的格式,我只实现了文件名部分,文档类型不知道如何实现。
这样上传后就取不到 type 的值curl_upload_server.php
<xmp>
<?php
print_r($_FILES);echo "文件内容:\n";
$p = current($_FILES);
readfile($p['tmp_name']);TEXT;$fields['f"; filename="x.x'] = $contents; //这个关联键的写法很怪异吧?$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://localhost/curl_upload_server.php");
curl_setopt($ch, CURLOPT_POST, 1 );
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);$s = curl_exec ($ch);
curl_close ($ch); echo $s;
$name = '3.txt';
$type = 'text/plain';
$key = <<< TEXT
$varname"; filename="$name
Content-Type: $typeTEXT;
$fields[$key] = $contents;注意:我是在 win 下的,linux 下要将 \n 换成 \r\n
没办法,早年的 sun 是拼不过 ms 的,现在也不行吧?一直以为上传的文件类型是 php 识别的,却原来是浏览器提供的
很感谢,有没有比较完整的CURL 通过拼接HTTPHEADER信息上传的POST示例呢?
curl_upload_server.php 就是测试用服务器端
<xmp>
<?php
print_r($_FILES);echo "文件内容:\n";
$p = current($_FILES);
readfile($p['tmp_name']);
<?php
//what file you want to upload
$uploadFile = file_get_contents("/var/www/index.html");
//content boundary
$boundary = md5(time());
$postStr = "";
$postStr .="--".$boundary."\r\n";
$postStr .="Content-Disposition: form-data; name=\"uptxt\"; filename=\"index.html\"\r\n";
$postStr .="Content-Type: text/html\r\n\r\n";
$postStr .=$uploadFile."\r\n";
$postStr .="--".$boundary."\r\n";
/** use fsockopen to set upload http header and body **/
$fp = fsockopen("localhost","80",$errer,$errno,1);
fwrite($fp,"POST /upload.php HTTP/1.0\r\n");
fwrite($fp,"Content-Type: multipart/form-data; boundary=".$boundary."\r\n");
fwrite($fp,"Content-length:".strlen($postStr)."\r\n\r\n");
fwrite($fp,$postStr);
while (!feof($fp)){
echo fgets($fp, 128);
}
fclose($fp);/** use curl instead **/
$cl = curl_init('http://localhost/upload.php');
$boundary = md5(time());
curl_setopt($cl,CURLOPT_POST,true);
curl_setopt($cl,CURLOPT_HTTPHEADER,array(
"Content-Type: multipart/form-data; boundary=".$boundary
));
curl_setopt($cl,CURLOPT_POSTFIELDS,$postStr);
curl_setopt($cl,CURLOPT_RETURNTRANSFER,true);
$content = curl_exec($cl);
curl_close($cl);
echo $content;
?>upload.php
<?php print_r($_FILES);?>结果
HTTP/1.1 200 OK
Server: nginx/0.8.54
Date: Tue, 10 Apr 2012 05:22:01 GMT
Content-Type: text/html
Connection: close
X-Powered-By: PHP/5.3.10Array
(
[uptxt] => Array
(
[name] => index.html
[type] => text/html
[tmp_name] => /tmp/phpKHfxkY
[error] => 0
[size] => 344
))
Array
(
[uptxt] => Array
(
[name] => index.html
[type] => text/html
[tmp_name] => /tmp/phpB0se13
[error] => 0
[size] => 344
))
非常感谢,CURL部分的代码我这边测试成功了,我再加一百分
#15 客户端#14 中的 $contents 是待上传的文件内容
$boundary = md5(time());
$postStr = "";
$postStr .="--".$boundary."\r\n";
$postStr .="Content-Disposition: form-data; name=\"uptxt[]\"; filename=\"index_1.html\"\r\n";
$postStr .="Content-Type: text/html\r\n\r\n";
$postStr .=$uploadFile."\r\n"; #这里是部分文件内容
$postStr .="--".$boundary."\r\n";$postStr .="--".$boundary."\r\n";
$postStr .="Content-Disposition: form-data; name=\"uptxt[]\"; filename=\"index_2.html\"\r\n";
$postStr .="Content-Type: text/html\r\n\r\n";
$postStr .=$uploadFile."\r\n";#这里是部分文件内容
$postStr .="--".$boundary."\r\n";
你这样做是不行的,应该使用 curl_multi 并发
不然把一个文件拆成几个,一次性传出,再在服务器端组装。有什么意义?
嗯,基本上都支持keep-alive了
照着PHP手册里去做反而没成功
我测试过的备份!http://webinno.cn/blog/article/view/40