[轉]檔案上傳原理:Web上傳檔案的原理及實現

來源:互聯網
上載者:User

標籤:des   style   blog   http   java   color   使用   os   

  現在有很多Web程式都有上傳功能,實現上傳功能的組件或架構也很多,如基於java的CommonsFileUpload、還有Struts1.x和Struts2中帶的上傳檔案功能(實際上,Struts2在底層也使用了CommonsFileUpload)。在asp.net中也有相應的上傳檔案的控制項。
  雖然現在有很多上傳組件可以利用,但是瞭解Web上傳檔案的原理,對於處理突然出現的問題會有很大的協助,下面就來講一下通過瀏覽器上傳檔案的基本原理。在瞭解了原理之後,就可以非常容易地自製滿足自身需要的上傳組件了。
  眾所周知,在用戶端代碼中需要使用<input type=‘file‘ name=‘file‘ />來選擇要上傳的檔案,並上傳,代碼如上:

<html><head><title>upload</title><meta http-equiv="description" content="this is my page"><meta http-equiv="content-type" content="text/html; charset=GB18030"></head><body><form action="servlet/UploadFile"   method="post"   enctype="multipart/form-data"><input type="file" name="file1" id="file1" /><input type="file" name="file2" id="file2" /><input type="submit" value="上傳" /></form></body></html>

      從上面的代碼可以看出,有兩個檔案選擇框(file1和file2),在上傳檔案時,<form>標籤必須加上enctype="multipart/form-data",否則瀏覽器無法將檔案內容上傳到服務端。下面我們來做個實驗。在Servlet的doPost方法中編寫如下的代碼,如果想使用asp.net或其他的語言或技術,也可以很容易實現相應的功能。

public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{  java.io.InputStream is = request.getInputStream();  java.io.FileOutputStream fos = new java.io.FileOutputStream("d:\\out.txt");  byte[] buffer = new byte[8192];  int count = 0;  while((count = is.read(buffer)) >0)  {    fos.write(buffer, 0, count);  }   fos.close();}

     上面的功能非常簡單,只是通過request獲得一個InputStream對象,並通過這個對象從用戶端獲得發送過來的位元組流(注意,一定要用位元組流,因為,上傳的檔案可能是二進位檔案,象檔案,因此,使用位元組流會更通用)。並將這些位元組流儲存在D盤的out.txt檔案中。然後我們開啟out.txt,檔案的內容1所示:

 

      由於out.txt是使用文本形式開啟的,並且file1上傳的是a.jpg(一個圖象檔案),因此,顯示的是一些亂碼。我們可以不用管它們。只需要看看這些內容的頭部。我們很快就可以找到規律。每一個檔案內容的頭部都由“-----------------------------30514443229777”分隔,然後是這個檔案的屬性,如下:
Content-Disposition: form-data; name="file1"; filename="a.jpg"
Content-Type: image/jpeg
  其中包含了檔案選擇框的name屬性,還有上傳的檔案名稱(filename欄位),要注意的,firefox在上傳時,這個filename屬性值只是檔案名稱,如果使用IE,就是帶路徑的檔案名稱,如D:"a.jpg。
  接下來的規則就和HTTP的頭一樣了,以一個空行("r"n)分隔。後面就是檔案的具體內容。現在最關鍵的檔案的結尾,從圖1可以看出,檔案的結尾也是

“-----------------------------30514443229777”,因此,可以斷定,第一個上傳的檔案(包括檔案頭)是夾在兩個

“-----------------------------30514443229777”之間的。而“-----------------------------30514443229777”就是multipart/form-data協議的分隔字元但這裡還有一個最關鍵的問題:這個分隔字元每次上傳都不一樣,服務端是如何知道每次上傳的這個分隔字元的呢?

     實際上,這個分隔字元是通過HTTP要求標頭的Content-Type欄位獲得,可通過下面的代碼輸出這個欄位值:     
      
                System.out.println(request.getHeader("Content-type"));

     輸出的內容如下:
                multipart/form-data; boundary=---------------------------106712230227687
     只要在服務端獲得boundary後面的值即可。經過測試,Content-Type中的分隔字元號中的“-”比實際上傳的“-”少兩個,不知是怎麼回事。不過這沒關係,我們可以認為每一個檔案塊是以""r"n—“結尾的,或是直接將從boundary獲得的分隔字元加兩個“—”。而最後結尾的分隔字元是
“---------------------------106712230227687—”,後面多了兩個“—”。

  綜合上述,也就是說,一個檔案塊是以“---------------------------106712230227687”開頭,以“—”結尾,從圖2可以看出這一切。

 

                圖2
         至於剩下的工作,就是按著上面的規則來分析這些字元流了。分析的方法很多。在這裡就不詳述了。

聯繫我們

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