200分CURL設定HTTPHEADER上傳檔案問題!

來源:互聯網
上載者:User
哪位大俠有使用CURL設定HTTPHEADER來上傳檔案的經驗?

求指點

PS:不是 '@'.檔案名稱,而是Content-Type: application/octet-stream


回複討論(解決方案)

curl不支援這種方式,你需要自己構造資料包。我研究過

curl不支援這種方式,你需要自己構造資料包。我研究過



是否有樣本?

http://cn.php.net/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.net/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">  <p class="yy">   原來這樣就有 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 下……  </p>  <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">  完整的代碼  <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']);  //輸出上傳的檔案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">  <p class="yy">   完整的代碼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(……  </p>  <br />  <br /> 沒有client? </p> <p class="sougouAnswer">  <p class="yy">   完整的代碼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(……  </p>  <br />  <br /> 最好能分開發一下,謝謝 </p> <p class="sougouAnswer">  <p class="yy">   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_……  </p>  <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">  <p class="yy">   上次好像看到你問的是一個檔案切分多份,然後上傳,如果是這樣的話,你要要做的只是用boundary標識多個上傳內容區塊。比如   <br /> PHP code   <br /> $boundary   = md5(time());   <br /> $postStr  = "";   <br /> $postStr .="--".$boundary."\r\n";   <br /> $postStr .="Content-Disposition: form-data; name=……  </p>  <br />  <br /> 我用了個迴圈來做 </p> <p class="sougouAnswer">  <p class="yy">   引用 21 樓  的回複:   <br />   <br /> 上次好像看到你問的是一個檔案切分多份,然後上傳,如果是這樣的話,你要要做的只是用boundary標識多個上傳內容區塊。比如   <br /> PHP code   <br /> $boundary   = md5(time());   <br /> $postStr  = "";   <br /> $postStr .="--".$boundary."\r\n";   <br /> $postStr .="Content-Dispositi……  </p>  <br />  <br /> 感謝,curl_multi很有用 </p> <p class="sougouAnswer">  <p class="yy">   to #21   <br /> 你這樣做是不行的,應該使用 curl_multi 並發   <br /> 不然把一個檔案拆成幾個,一次性傳出,再在伺服器端組裝。有什麼意義?  </p>  <br /> 說的也是哈,不過curl_multi的並發,對於請求不同的url後擷取資料比較有意義,就是說是並行請求不同的url擷取http返回。如果往同一url請求,要麼就一次請求,要麼就分發多次請求,多次請求有個效能消耗在於每次都要scoket串連/銷毀,但是能控制請求位元組數。 </p> <p class="sougouAnswer">  <p class="yy">   引用 23 樓  的回複:   <br />   <br /> to #21   <br /> 你這樣做是不行的,應該使用 curl_multi 並發   <br /> 不然把一個檔案拆成幾個,一次性傳出,再在伺服器端組裝。有什麼意義?   <br />   <br /> 說的也是哈,不過curl_multi的並發,對於請求不同的url後擷取資料比較有意義,就是說是並行請求不同的url擷取http返回。如果往同一url請求,要麼就一次請求,要麼就分發多次請求,多次請求有個效能消耗在於每……  </p>  <br /> 忘了如果伺服器支援keep-alive的話,無需進行多次socket create,呵呵 </p> <p class="sougouAnswer">  一路上傳不能充分利用網路資源,多路並發可使上傳速度加快  <br /> </p> <p class="sougouAnswer">  <p class="yy">   引用 26 樓  的回複:   <br />   <br /> 引用 23 樓  的回複:   <br />   <br /> to #21   <br /> 你這樣做是不行的,應該使用 curl_multi 並發   <br /> 不然把一個檔案拆成幾個,一次性傳出,再在伺服器端組裝。有什麼意義?   <br />   <br /> 說的也是哈,不過curl_multi的並發,對於請求不同的url後擷取資料比較有意義,就是說是並行請求不同的url擷取http返回。如果往同一url請求,要麼就一次請求,要麼就分發多……  </p>  <br />  <br /> 嗯,基本上都支援keep-alive了 </p> <p class="sougouAnswer">  <p class="yy">   一路上傳不能充分利用網路資源,多路並發可使上傳速度加快  </p>  <br />  <br /> 嗯,網路利用率更高 </p> <p class="sougouAnswer">  CSDN的編輯器還是沒改進,同時回複多個還需要手動複製代碼。。。 </p> <p class="sougouAnswer">  嗯,伺服器可開多線程/進程處理你的並發上傳請求,這是快的緣故。 </p> <p class="sougouAnswer">  只要資源夠,多開幾路並無大礙,至多大部被阻塞了,就相當於單路  <br /> 設計成多路傳輸的好處還有,當某段資料轉送失敗時,可以重傳這段。  <br /> 這是單路傳輸設計做不到的 </p> <p class="sougouAnswer">  <p class="yy">   http://cn.php.net/fsockopen   <br /> CTRL + F搜尋boundary,例子好好看看,構建一個檔案上傳的http要求標頭即可,按理說CURL構建同樣的要求標頭應該也沒問題。  </p>  <br />  <br /> 照著PHP手冊裡去做反而沒成功 </p> <p class="sougouAnswer">  <p class="yy">   引用 5 樓  的回複:   <br />   <br /> http://cn.php.net/fsockopen   <br /> CTRL + F搜尋boundary,例子好好看看,構建一個檔案上傳的http要求標頭即可,按理說CURL構建同樣的要求標頭應該也沒問題。   <br />   <br />   <br /> 照著PHP手冊裡去做反而沒成功  </p>  <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">  我也要一份<li ><i class="layui-icon">&#xe63a;
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.