類比POST上傳檔案

來源:互聯網
上載者:User

標籤:style   blog   http   color   io   os   java   ar   for   

  上傳下載檔案在瀏覽器裡面都非常簡單,上傳檔案在瀏覽器裡就是幾個標籤,中間到底發生了什麼我們全然不知,而下載檔案更是簡單——下載檔案只需獲得檔案的地址以二進位的方式寫出來就好。最近有個同學想在安卓裡面做一個上傳功能的App,最簡單的莫過於HTTP的POST方法了(fork this  https://www.imququ.com/post/four-ways-to-post-data-in-http.html)。

  可以先觀察下上傳檔案的HTTP Header:

可以看到Request Header後面多了一個沒有見過的 Request Payload, 這個Request Payload 正是上傳檔案的關鍵,我的理解主要參考 http://jackface.iteye.com/blog/2098604,這篇文章詳細的介紹了他在後台抓取到的POST的資訊的格式,對,POST傳送檔案的時候格式一定要嚴格,否則就上傳不了(我已經做過多次實驗),文章裡抓到的資料和 Request Payload裡的資料差不多,知識Payload裡面沒有檔案的二進位流。

  總結一下,POST上傳檔案的要點:   

  一、boundary是瀏覽器隨機產生的分隔字元(要求標頭裡面有),要求標頭裡面的boundary前面是四個"-",而Payload裡面的是六個,多的兩個叫做 prefix(首碼),然後就是結束的地方又有兩個prefix(怎麼感覺應該叫做尾碼)

  二、換行都是"\r\n"

  三、只有最後結束的地方才會多一個首碼,如果是多個檔案上傳,前面的都一樣只有最後一個會多一個首碼

附java實現代碼(照著網上的改的):

  1 import java.io.ByteArrayOutputStream;  2 import java.io.File;  3 import java.io.FileInputStream;  4 import java.io.FileNotFoundException;  5 import java.io.IOException;  6 import java.io.InputStream;  7 import java.io.OutputStream;  8 import java.net.HttpURLConnection;  9 import java.net.MalformedURLException; 10 import java.net.URL; 11  12 public class Poster 13 { 14   static String boundary = "--------------7d226f700d0"; 15   static String prefix = "--"; 16   static String newLine = "\r\n"; 17   public static void main(String args[]) 18   { 19     test(); 20   } 21   private static void test() 22   { 23     try 24     { 25        26       URL url = new URL("http://1.crackme.sinaapp.com/scripts/upload.php");//post address 27       HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 28       connection.setDoInput(true); 29       connection.setDoOutput(true); 30  31       connection.setRequestProperty("Content-type","multipart/form-data;boundary="+boundary);  32       AssemblyHttp(connection.getOutputStream()); 33       InputStream ins = connection.getInputStream(); 34       byte[] b = readBuffer(ins); 35       System.out.println(new String(b)); 36     } catch (MalformedURLException e) 37     { 38       System.out.println(" URL address error "); 39     } catch (IOException e) 40     { 41       System.out.println(" URL open error "); 42     } 43   } 44   private static void AssemblyHttp(OutputStream out) 45   { 46     StringBuffer params = new StringBuffer(); 47        48     params.append(prefix+boundary + newLine); 49                                                   //name is the the key "name"‘s value in the upload form 50     params.append("Content-Disposition: form-data; name=\"myfile[]\";filename="+"\"20140821182141.jpg\""); 51     params.append(newLine);        52     params.append("Content-Type: image/jpeg"); 53     params.append(newLine+newLine); 54      55     StringBuffer params2 = new StringBuffer(); 56        57     params2.append(prefix+boundary + newLine); 58                                                                  59     params2.append("Content-Disposition: form-data; name=\"myfile[]\";filename="+"\"6b68a43308f198a375d9369a39c7ee1e.jpg\""); 60     params2.append(newLine);        61     params2.append("Content-Type: image/jpeg"); 62     params2.append(newLine+newLine); 63  64  65     File file = new File("C:\\Users\\KL\\Pictures\\20140821182141.jpg"); 66     File file2 = new File("C:\\Users\\KL\\Pictures\\6b68a43308f198a375d9369a39c7ee1e.jpg"); 67     try 68     { 69       InputStream in = new FileInputStream(file); 70       out.write(params.toString().getBytes());                    71       out.write(readBuffer(in)); 72       out.write(newLine.getBytes());            73       out.write((prefix+boundary+newLine).getBytes()); 74  75  76       InputStream in2 = new FileInputStream(file2); 77       out.write(params2.toString().getBytes());                    78       out.write(readBuffer(in2)); 79       out.write(newLine.getBytes()); 80  81       out.write((prefix+boundary + prefix).getBytes()); 82       out.flush(); 83       out.close();          84     } catch (FileNotFoundException e) 85     { 86       System.out.println(" file not found  "); 87     } catch (IOException e) 88     { 89       System.out.println(" IO Error "); 90     } 91   } 92  93  94   public static byte[] readBuffer(InputStream ins) throws IOException 95   { 96     byte b[] = new byte[1024]; 97     ByteArrayOutputStream stream = new ByteArrayOutputStream(); 98     int len = 0; 99     while((len=ins.read(b))!= -1)100     {101       stream.write(b, 0, len);102     }103     return stream.toByteArray();104   }105 }
View Code

 

用java寫可以看到好多上傳的細節,用Python的第三方庫就非常簡潔了,libcurl(fork this http://curl.haxx.se/libcurl/)有python的移植但是有點太龐大的,配置起來也不好配置,poster 也是python的一個第三方庫,用起來非常方便,代碼如下:

 1 # test_client.py 2 from poster.encode import multipart_encode 3 from poster.streaminghttp import register_openers 4 import urllib2 5  6 url = ["http://1.crackme.sinaapp.com/scripts/upload.php","http://localhost/learnPHP/scripts/upload.php"] 7  8 register_openers() 9 10 11 datagen, headers = multipart_encode({"myfile": open("C:\\Users\\KL\\Pictures\\20140821182141.jpg", "rb")})12 13 14 request = urllib2.Request(url[0], datagen, headers)15 16 print urllib2.urlopen(request).read()
View Code

(fork this http://alexliyu.blog.163.com/blog/static/162754496201252154412432/)

類比POST上傳檔案

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.