输入banner图图片脚本导航/分类

200分求助CURL设置HTTPHEADER上传文件问题!

哪位大侠有使用CURL设置HTTPHEADER来上传文件的经验?

求指点

PS:不是 '@'.文件名,而是Content-Type: application/octet-stream


回复讨论(解决方案)

curl不支持这种方式,你需要自己构造数据包。我研究过

curl不支持这种方式,你需要自己构造数据包。我研究过

是否有示例?

http://cn.php.com/fsockopen
CTRL + 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);

总结一下项目中用到curl的几种方式
1. php curl的默认调用方法,get方式访问url
Java代码
....
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //设置http头
curl_setopt($ch, CURLOPT_ENCO……

貌似没看到使用了CURLOPT_HTTPHEADER

http://cn.php.com/fsockopen
CTRL + F搜索boundary,例子好好看看,构建一个文件上传的http请求头即可,按理说CURL构建同样的请求头应该也没问题。

谢谢,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<?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;</pre> </p> <p class="sougouAnswer">  原来这样就有 type了  <pre class="sycode" name="code">$varname = 'my';$name = '3.txt';$type = 'text/plain';$key = <<< TEXT$varname"; filename="$nameContent-Type: $typeTEXT;$fields[$key] = $contents;</pre>  <br /> 注意:我是在 win 下的,linux 下要将 \n 换成 \r\n  <br /> 没办法,早年的 sun 是拼不过 ms 的,现在也不行吧?  <br />  <br /> 一直以为上传的文件类型是 php 识别的,却原来是浏览器提供的 </p> <p class="sougouAnswer">  原来这样就有 type了PHP code  <br /> $varname = 'my';  <br /> $name = '3.txt';  <br /> $type = 'text/plain';  <br /> $key = <<< TEXT  <br /> $varname"; filename="$name  <br /> Content-Type: $type  <br />  <br /> TEXT;  <br /> $fields[$key] = $contents;  <br />  <br />  <br /> 注意:我是在 win 下的,linux 下……  <br />  <br /> 很感谢,有没有比较完整的CURL 通过拼接HTTPHEADER信息上传的POST示例呢? </p> <p class="sougouAnswer">  #10 就是  <br /> curl_upload_server.php 就是测试用服务器端  <br /> <xmp>  <br /> <?php  <br /> print_r($_FILES);  <br />  <br /> echo "文件内容:\n";  <br /> $p = current($_FILES);  <br /> readfile($p['tmp_name']);  <br /> </p> <p class="sougouAnswer">  <p class="modified_message">   本帖最后由 xuzuning 于 2012-04-10 13:19:42 编辑  </p> 完整的代码  <pre class="sycode" name="code">$contents =<<< 'TEXT'数据报中应该是Content-Disposition: form-data; name="userfile"; filename="file_name"Content-Type: 文档类型文件内容这样的格式以下是服务器端代码curl_upload_server.php<xmp><?phpprint_r($_FILES); //检查上传信息echo "文件内容:\n";$p = current($_FILES);readfile($p['tmp_name']);  //</pre>输出上传的文件TEXT;$varname = 'my';$name = '3.txt';$type = 'text/plain';$key = "$varname\"; filename=\"$name\r\nContent-Type: $type\r\n";$fields[$key] = $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;</pre> </p> <p class="sougouAnswer">  http文件上传协议,主要是那个boundary,这个东西就是标识一个文件的内容和类型以及各种上传参数的token,其它和普通的POST提交也没啥区别。  <br />  <br /> fsockopen来写http请求就比较直白,用curl的话模拟对应的请求头和body就好了。  <br />  <pre class="sycode" name="code"><?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;?></pre>  <br />  <br /> upload.php  <br />  <pre class="sycode" name="code"><?php print_r($_FILES);?></pre>  <br />  <br /> 结果  <br />  <pre class="sycode" name="code">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        ))</pre>  <br />  <br />  <br />  <br /> </p> <p class="sougouAnswer">  完整的代码PHP code  <br /> $contents =<<< 'TEXT'  <br /> 数据报中应该是  <br /> Content-Disposition: form-data; name="userfile"; filename="file_name"  <br /> Content-Type: 文档类型  <br />  <br /> 文件内容  <br />  <br /> 这样的格式  <br /> 以下是服务器端代码  <br /> curl_upload_server.php  <br /> <xmp>  <br /> <?php  <br /> print_r(……  <br />  <br /> 没有client? </p> <p class="sougouAnswer">  完整的代码PHP code  <br /> $contents =<<< 'TEXT'  <br /> 数据报中应该是  <br /> Content-Disposition: form-data; name="userfile"; filename="file_name"  <br /> Content-Type: 文档类型  <br />  <br /> 文件内容  <br />  <br /> 这样的格式  <br /> 以下是服务器端代码  <br /> curl_upload_server.php  <br /> <xmp>  <br /> <?php  <br /> print_r(……  <br />  <br /> 最好能分开发一下,谢谢 </p> <p class="sougouAnswer">  http文件上传协议,主要是那个boundary,这个东西就是标识一个文件的内容和类型以及各种上传参数的token,其它和普通的POST提交也没啥区别。  <br />  <br /> fsockopen来写http请求就比较直白,用curl的话模拟对应的请求头和body就好了。  <br /> PHP code  <br /> <?php  <br /> //what file you want to upload  <br /> $uploadFile = file_get_……  <br />  <br /> 非常感谢,CURL部分的代码我这边测试成功了,我再加一百分 </p> <p class="sougouAnswer">  #14 服务器端  <br /> #15 客户端  <br />  <br /> #14 中的 $contents 是待上传的文件内容 </p> <p class="sougouAnswer">  上次好像看到你问的是一个文件切分多份,然后上传,如果是这样的话,你要要做的只是用boundary标识多个上传内容区块。比如  <br />  <pre class="sycode" name="code">$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";</pre>  <br /> </p> <p class="sougouAnswer">  收藏了! </p> <p class="sougouAnswer">  to #21  <br /> 你这样做是不行的,应该使用 curl_multi 并发  <br /> 不然把一个文件拆成几个, 一次性传出,再在服务器端组装。有什么意义?  <br /> </p> <p class="sougouAnswer">  上次好像看到你问的是一个文件切分多份,然后上传,如果是这样的话,你要要做的只是用boundary标识多个上传内容区块。比如  <br /> PHP code  <br /> $boundary   = md5(time());  <br /> $postStr  = "";  <br /> $postStr .="--".$boundary."\r\n";  <br /> $postStr .="Content-Disposition: form-data; name=……  <br />  <br /> 我用了个循环来做 </p> <p class="sougouAnswer">  引用 21 楼  的回复:  <br />  <br /> 上次好像看到你问的是一个文件切分多份,然后上传,如果是这样的话,你要要做的只是用boundary标识多个上传内容区块。比如  <br /> PHP code  <br /> $boundary   = md5(time());  <br /> $postStr  = "";  <br /> $postStr .="--".$boundary."\r\n";  <br /> $postStr .="Content-Dispositi……  <br />  <br /> 感谢,curl_multi很有用 </p> <p class="sougouAnswer">  to #21  <br /> 你这样做是不行的,应该使用 curl_multi 并发  <br /> 不然把一个文件拆成几个,一次性传出,再在服务器端组装。有什么意义?  <br /> 说的也是哈,不过curl_multi的并发,对于请求不同的url后获取数据比较有意义,就是说是并行请求不同的url获取http返回。如果往同一url请求,要么就一次请求,要么就分发多次请求,多次请求有个性能消耗在于每次都要scoket连接/销毁,但是能控制请求字节数。 </p> <p class="sougouAnswer">  引用 23 楼  的回复:  <br />  <br /> to #21  <br /> 你这样做是不行的,应该使用 curl_multi 并发  <br /> 不然把一个文件拆成几个,一次性传出,再在服务器端组装。有什么意义?  <br />  <br /> 说的也是哈,不过curl_multi的并发,对于请求不同的url后获取数据比较有意义,就是说是并行请求不同的url获取http返回。如果往同一url请求,要么就一次请求,要么就分发多次请求,多次请求有个性能消耗在于每……  <br /> 忘了如果服务器支持keep-alive的话,无需进行多次socket create,呵呵 </p> <p class="sougouAnswer">  一路上传不能充分利用网络资源,多路并发可使上传速度加快  <br /> </p> <p class="sougouAnswer">  引用 26 楼  的回复:  <br />  <br /> 引用 23 楼  的回复:  <br />  <br /> to #21  <br /> 你这样做是不行的,应该使用 curl_multi 并发  <br /> 不然把一个文件拆成几个,一次性传出,再在服务器端组装。有什么意义?  <br />  <br /> 说的也是哈,不过curl_multi的并发,对于请求不同的url后获取数据比较有意义,就是说是并行请求不同的url获取http返回。如果往同一url请求,要么就一次请求,要么就分发多……  <br />  <br /> 嗯,基本上都支持keep-alive了 </p> <p class="sougouAnswer">  一路上传不能充分利用网络资源,多路并发可使上传速度加快  <br />  <br /> 嗯,网络利用率更高 </p> <p class="sougouAnswer">  CSDN的编辑器还是没改进,同时回复多个还需要手动。。。 </p> <p class="sougouAnswer">  嗯,服务器可开多线程/进程处理你的并发上传请求,这是快的缘故。 </p> <p class="sougouAnswer">  只要资源够,多开几路并无大碍,至多大部被阻塞了,就相当于单路  <br /> 设计成多路传输的好处还有,当某段数据传输失败时,可以重传这段。  <br /> 这是单路传输设计做不到的 </p> <p class="sougouAnswer">  http://cn.php.com/fsockopen  <br /> CTRL + F搜索boundary,例子好好看看,构建一个文件上传的http请求头即可,按理说CURL构建同样的请求头应该也没问题。  <br />  <br /> 照着PHP手册里去做反而没成功 </p> <p class="sougouAnswer">  引用 5 楼  的回复:  <br />  <br /> http://cn.php.com/fsockopen  <br /> CTRL + F搜索boundary,例子好好看看,构建一个文件上传的http请求头即可,按理说CURL构建同样的请求头应该也没问题。  <br />  <br />  <br /> 照着PHP手册里去做反而没成功  <br /> 是吗?你不如用wireshark,smartsniff等工具查看http请求格式(firebug或者chrome自带的F12应该也可以),执行一次上传文件动作,然后观察文件上传时的http请求格式。 </p> <p class="sougouAnswer">  贴个post的socket代码:  <br /> 我测试过的备份!  <br />  <br /> http://webinno.cn/blog/article/view/40  <br />  <br /> </p> <p class="sougouAnswer">  CURLOPT_HEADERFUNCTION这个参数可以设置HTTP协议回调,你可以参考下 </p> <p class="sougouAnswer">  curl只要你设置些参数,然后他自己会生成协议头提交服务器 </p> <p class="sougouAnswer">  谢谢大家! </p> <p class="sougouAnswer">  我只用过Content-Type提供下载. </p> <p class="sougouAnswer">  不错!!!!!! </p> <p class="sougouAnswer">  我也要一份  </div>

  </div>

<script type="text/javascript" src="/layui/layui.js"></script>
<script>
layui.use('code', function(){
  
layui.code({
  elem: 'pre', //默认值为.layui-code
  about:false,
  title:'200分求助CURL设置HTTPHEADER上传文件问题!代码块',
  encode: true //是否转义html标签。默认不开启
});
});
</script>
<footer class="comm-footer">
           <ul class="channels">
              <li>
                <a target="_top" href="/system/">操作系统</a>
            </li><li>
                <a target="_top" href="/down/">程序下载</a>
            </li><li>
                <a target="_top" href="/jquery/">jquery插件库</a>
            </li><li>
                <a target="_top" href="/jiaoben/">编程</a>
            </li><li>
                <a target="_top" href="/db/">数据库</a>
            </li><li>
                <a target="_top" href="/tools/">在线工具</a>
            </li><li>
                <a target="_top" href="/framebook/">框架书籍</a>
            </li><li>
                <a target="_top" href="/xitongjiaocheng/">系统教程</a>
            </li><li>
                <a target="_top" href="/ruanjianxiazai/">软件下载</a>
            </li>            </ul>
            <ul class="versions">
            <li>
                <a href="https://m.gxlcms.com" class="active">触屏版</a>
            </li>

            <li>
                <a href="https://www.gxlcms.com" target="_top">电脑版</a>
            </li>
            </ul>
           
              
     
        <p><a href="https://beian.miit.gov.cn/" target="_blank"  style="color:#ffffff"></a><script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?6c9b8cea1903c9f813f150c04aeebc3c";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script></p>
        </footer>	

</body>
</html>