Web上傳檔案的原理及實現
現在有很多Web程式都有上傳功能,實現上傳功能的元件或框架也很多,如基於java的Commons FileUpload、還有Struts1.x和Struts2中帶的上傳檔案功能(實際上,Struts2在底層也使用了Commons FileUpload)。在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>
<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();
}
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所示:
圖1
由於out.txt是使用文字形式開啟的,並且file1上傳的是a.jpg(一個圖象檔案),因此,顯示的是一些亂碼。我們可以不用管它們。只需要看看這些內容的頭部。我們很快就可以找到規律。每一個檔案內容的頭部都由“-----------------------------30514443229777”分隔,然後是這個檔案的屬性,如下:
Content-Disposition: form-data; name="file1"; filename="a.jpg"
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"));
System.out.println(request.getHeader("Content-type"));
輸出的內容如下:
multipart/form-data; boundary=---------------------------106712230227687
multipart/form-data; boundary=---------------------------106712230227687
只要在服務端獲得boundary後面的值即可。經過測試,Content-Type中的分隔符號中的“-”比實際上傳的“-”少兩個,不知是怎麼回事。不過這沒關係,我們可以認為每一個檔案塊是以""r"n—“結尾的,或是直接將從boundary獲得的分隔符加兩個“—”。而最後結尾的分隔符是“---------------------------106712230227687—”,後面多了兩個“—”。
綜合上述,也就是說,一個檔案塊是以“---------------------------106712230227687”開頭,以“—”結尾,從圖2可以看出這一切。
圖2
圖2
至於剩下的工作,就是按著上面的規則來分析這些字元流了。分析的方法很多。在這裡就不詳述了。
multipart/form-data規 範原文:http://www.ietf.org/rfc/rfc2388.txt
multipart/form-data規 範原文:http://www.ietf.org/rfc/rfc2388.txt
Form-based File Upload in HTML:http://www.ietf.org/rfc/rfc1867.txt
本文轉自 androidguy 51CTO部落格,原文連結:http://blog.51cto.com/androidguy/215335,如需轉載請自行聯絡原作者
相關文章
- 檔案上傳原理和實現
- 大檔案上傳原理及實現方案 | 京東物流技術團隊
- Node + js實現大檔案分片上傳基本原理及實踐(一)JS
- 檔案上傳踩坑記及檔案清理原理探究
- Solon Web 檔案上傳的最佳實踐Web
- AngularJS實現的檔案檔案上傳AngularJS
- C#實現Web檔案上傳的兩種方法(轉)C#Web
- ajax實現檔案上傳
- PHP實現單檔案、多檔案上傳 封裝 物件導向實現檔案上傳PHP封裝物件
- .net web core 如何編碼實現檔案上傳功能Web
- HTTP檔案上傳原理HTTP
- Java Web 檔案上傳JavaWeb
- WEB漏洞——檔案上傳Web
- js實現帶上傳進度的檔案上傳JS
- Java實現上傳檔案到Oracle及從Oracle下載檔案JavaOracle
- 使用java的MultipartFile實現layui官網檔案上傳實現全部示例,java檔案上傳JavaUI
- HttpFileCollection 實現多檔案上傳HTTP
- springmvc實現檔案上傳SpringMVC
- Web安全-檔案上傳漏洞Web
- Web安全之檔案上傳Web
- WEB安全:檔案上傳漏洞Web
- Jsp+Servlet實現檔案上傳下載(一)--檔案上傳JSServlet
- 通過配置檔案(.htaccess)實現檔案上傳
- PHP實現圖片(檔案)上傳PHP
- Java檔案上傳如何實現呢?Java
- 關於node實現檔案上傳
- 使用Spring實現上傳檔案Spring
- Spring mvc檔案上傳實現SpringMVC
- JS實現檔案自動上傳JS
- .NET Core 如何上傳檔案及處理大檔案上傳
- java實現sftp檔案的上傳下載JavaFTP
- <web滲透-檔案上傳漏洞>Web
- Django2 Web 實戰03-檔案上傳DjangoWeb
- [提問交流]上傳web原始碼檔案模板的線上預覽實現方法?Web原始碼
- struts動態多檔案上傳實現
- 【node】檔案上傳功能簡易實現
- 自定義檔案上傳功能實現方法
- SpringMVC多個檔案上傳實現SpringMVC