用commons-fileupload實現檔案上傳
Form表單的要求
1.提供from表單,method必須是post(post方式可以提交大量資料)
2.提供input type=”file”標籤
3.form表單的enctype屬性必須是multipart/form-data(就是在設定請求訊息頭的Content-Type)
- application/x-www-form-urlencoded(預設)。請求報文內容的格式為name=admin&password=123。伺服器通過request.getParameter(“name”);來獲取資料
- multipart/form-data。請求報文內容的格式為
Content-Type : multipart/form-data; boundary=---------------------------28512195225210
Content-Length: 295
-----------------------------28512195225210
Content-Disposition: form-data; name="a"
q
-----------------------------28512195225210
Content-Disposition: form-data; name="b"; filename="a.txt"
Content-Type: text /plain
eaglezsx
-----------------------------28512195225210--
資料被分隔線分成一段一段的,其中每兩個分隔線之間的資料稱為一個item。request.getParameter(“name”)方法獲取指定的表單欄位字元內容,但檔案上傳表單已經不再是字元內容,而是位元組內容,所以失效。用request.getInputStream();方法可以獲取位元組流。
例子
新建一個a.txt,裡邊隨便寫點兒東西,eaglezsx。
新建一個upload.jsp
<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/servlet/uploadServlet" method="post">
<input type="text" name="a" />
<input type="file" name="b"/></br>
<input type="submit" value="提交"/>
</form>
新建一個Servlet,UploadServlet.java
public class UploadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletInputStream sis=request.getInputStream();//獲取請求報文中的內容
int len=-1;
byte[] b=new byte[1024];
while ((len=sis.read(b))!=-1) {
System.out.println(new String(b,0,len));//將請求報文中的內容轉化為字串,列印到控制檯
}
sis.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
執行結果為
-----------------------------17157105472171
Content-Disposition: form-data; name="a"
hello
-----------------------------17157105472171
Content-Disposition: form-data; name="b"; filename="a.txt"
Content-Type: text/plain
eaglezsx
-----------------------------17157105472171--
這就是從瀏覽器接收到的那些東西。把這些東西解析了,就可以獲得需要的內容了。自己解析起來比較麻煩。有現成的元件commons fileupload來解析這些請求。Apache的官網有它的使用者指南http://commons.apache.org/proper/commons-fileupload/using.html裡邊有個小例子。
在使用FileUpload元件時,需要匯入commons-fileupload和commons-io兩個jar包。
通過這個例子,可以看出主要用這幾樣東西
DiskFileItemFactory類
如果上傳的檔案比較小,將儲存在記憶體中。如果上傳的檔案比較大,則會以臨時檔案的形式儲存在磁碟的臨時資料夾中。預設情況下,檔案儲存在記憶體還是硬碟臨時資料夾的臨界值是10240,即10K。
構造方法
- DiskFileItemFactory():採用預設臨界值10240,預設臨時資料夾為D:\Java\apache-tomcat-7.0.52\temp,Tomcat安裝目錄中的temp資料夾中。
- DiskFileItemFactory(int sizeThreshold,File repository):採用引數指定臨界值和臨時檔案的儲存位置
方法
- setSizeThreshold(int sizeThreshold):設定臨界值
- setRepository(File repository):設定臨時檔案的儲存位置
ServletFileUpload類
構造方法:
- ServletFileUpload(FileItemFactory fileItemFactory)
方法:
- parseRequest(HttpServletRequest req):解析出Form表單中的每個欄位的資料,並將它們分別包裝成獨立的FileItem物件,然後將這些FileItem物件加入進一個List型別的集合物件中返回。
- isMultipartContent():是個靜態方法,判斷請求訊息中的內容是否是multipart/form-data型別,如果是則返回true。
FileItem介面
- boolean isFormFiled():用於判斷FileItem類物件封裝的資料是一個普通文字表單欄位,還是一個檔案表單欄位,如果是普通表單欄位則返回true。
- String getFiledName():獲取表單欄位name屬性的值。
- String getName():獲取檔案上傳欄位中的檔名
- String getString():獲取普通欄位的value屬性的值。
- String getString(String encoding):可以設定編碼,這樣普通標籤的value為中文時就不會亂碼了
void write(File file):將FileItem物件中儲存的主體內容儲存到某個指定的檔案中。如果內容是在臨時檔案中,那麼DiskFileItem被垃圾回收後,臨時檔案會被自動刪除。
String getContentType():獲取上傳檔案的型別,即表單欄位描述頭屬性Content-Type的值,如“image/jpeg”。
- boolean isInMemory():判斷FileItem物件封裝的資料內容是儲存在記憶體中,還是儲存在臨時檔案中,在記憶體中則返回true。
- long getSize():返回該上傳檔案的大小(以位元組為單位)
- InputStream getInputStream():以流的形式返回上傳檔案的內容
public class UploadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if (ServletFileUpload.isMultipartContent(request)) {
File repository=new File("G:/");
DiskFileItemFactory factory=new DiskFileItemFactory(1024*1024, repository);
ServletFileUpload upload=new ServletFileUpload(factory);
try {
List<FileItem> items=upload.parseRequest(request);//這句話執行就會開始產生臨時檔案,這句話執行完後,臨時檔案也就產生了,臨時檔案和上傳的檔案一樣大,後面的操作都是對臨時檔案的操作
for (FileItem item : items) {
if (item.isFormField()) {
processFormField(item);
}else {
try {
processUploadedFile(item);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}else {
System.out.println("這不是檔案上傳表單");
}
}
private void processUploadedFile(FileItem item) throws Exception {
String fieldName=item.getFieldName();
String fileName=item.getName();
String contentType=item.getContentType();
boolean isInMemory=item.isInMemory();
long sizeInBytes=item.getSize();
System.out.println(fieldName+" "+fileName+" "+contentType+" "+" "+isInMemory+" "+sizeInBytes);
//把上傳的檔案儲存d盤
File uploadedFile=new File("D:/"+fileName);
item.write(uploadedFile);//這種方式臨時檔案會自動刪除
//或者採用流的形式操作資料,這種方式需要呼叫delete方法來刪除臨時檔案
/*
InputStream uploadedStream=item.getInputStream();
FileOutputStream fos=new FileOutputStream(uploadedFile);
int len=0;
byte[] b=new byte[1024];
while((len=uploadedStream.read(b))!=-1){
fos.write(b,0,len);
}
uploadedStream.close();
fos.close();
item.delete();
*/
}
private void processFormField(FileItem item) {
String name=item.getFieldName();
String value=item.getString();
System.out.println("name:"+name+"---"+"value:"+value);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
顯示結果為
name:a---value:hello
b a.txt text/plain true 8
需要注意的問題
1.getName()在有的瀏覽器中獲取的是檔名(a.txt),但在有些瀏覽器中獲取的就是完整的路徑(C:\Users\YZ\Desktop\a.txt)。
解決方法
String filename=fileitem.getName();
filename=filename.substring(filename.lastIndexOf(File.separator)+1);
filename=FilenameUtils.getName(filename);
2.如果客戶端上傳了一個jsp,上面寫著一段讓伺服器關機的程式碼。之後客戶端訪問這個jsp,jsp裡邊的程式碼就會執行。
為了保證伺服器的安全,把上傳檔案的目錄放在使用者訪問不到的地方。WEB-INF下
File uploadedFile=new File(this.getServletContext().getRealPath("/WEB-INF/uploadedfile"));
3.如果上傳的檔名稱相同,以前的檔案會被覆蓋
讓檔名唯一即可
filename=UUID.randomUUID()+"_"+filename;
4.把檔案都放到一個資料夾裡到時候檢索的時候會很慢
把檔案打散,弄一些子目錄
- 通過日期打散
File uploadedFile=new File(this.getServletContext().getRealPath("/WEB-INF/uploadedfile"));
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
String date=sdf.format(new Date());
uploadedFile=new File(uploadedFile,date);
- 通過雜湊值打散
int hashcode=fileName.hashCode();//返回此物件的雜湊值
String code=Integer.toHexString(hashcode);//將其轉換為16進位制的字元,se3343ie
String childDirectory=code.charAt(0)+File.separator+code.charAt(1);// s/e
uploadedFile=new File(uploadedFile,childDirectory);
5.限制檔案的大小
ServletFileUpload中的
- setFileSizeMax(位元組):設定單個檔案的大小
- setSizeMax(位元組):總檔案大小(多檔案上傳)
6.使用者沒有選擇檔案,就點選了上傳
判斷檔名是否為空即可
7.檔名為中文時會亂碼。
用ServletFileUpload的setHeaderEncoding方法設定一下。
8.普通欄位的value為中文時會亂碼
String value=item.getString("utf-8");
用Streaming API實現上傳
前面用的是傳統的API實現上傳,commons-fileupload還有一套Streaming API。官方文件http://commons.apache.org/proper/commons-fileupload/streaming.html說這種方法沒有傳統方法便利,但效能更好。傳統方法有多便利我沒看出來(有知道的,麻煩告訴我一下),但Streaming API在效能上的提升確可以明顯的看出來。傳統方法中,上傳的檔案都要先儲存到記憶體或臨時檔案中,然後在對記憶體或臨時檔案進行操作。這樣的話,如果我上傳的大檔案,相當於操作了檔案兩遍,先把上傳檔案弄到快取檔案中,再把快取檔案複製一份到最終目錄。如果用Streaming API的話,直接把上傳的檔案傳到最終的目錄。
public class UploadServlet2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if (ServletFileUpload.isMultipartContent(request)) {
ServletFileUpload upload=new ServletFileUpload();
try {
FileItemIterator iter = upload.getItemIterator(request);
while(iter.hasNext()){
FileItemStream item=iter.next();
String name=item.getFieldName();//獲取name屬性的值
if(item.isFormField()){
processFormField(item);
}else{
processUploadedFile(item);
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}else {
System.out.println("這不是檔案上傳表單");
}
}
private void processUploadedFile(FileItemStream item) throws IOException{
InputStream is=item.openStream();
FileOutputStream fos=new FileOutputStream(new File("D:/"+item.getName()));
int len=-1;
byte[] b=new byte[1024*1024];
while((len=is.read(b))!=-1){
fos.write(b, 0, len);
}
is.close();
fos.close();
}
private void processFormField(FileItemStream item) throws IOException {
String name=item.getFieldName();
InputStream is=item.openStream();
String value=Streams.asString(is);
System.out.println("name:"+name+"---"+"value:"+value);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
相關推薦
用commons-fileupload實現檔案上傳
Form表單的要求 1.提供from表單,method必須是post(post方式可以提交大量資料) 2.提供input type=”file”標籤 3.form表單的enctype屬性必須是multipart/form-data(就是在設定請求訊息頭的C
Apache Commons FileUpload實現檔案上傳
Commons FileUpload簡介 Apache Commons是一個專注於可重用Java元件開發的 Apache 專案。Apache Commons專案由三個部分組成: 1、Commons Proper - 可重用Java元件的儲存庫。 2、The Commons Sandbox - 用於Jav
commons-fileupload實現檔案上傳
一、準備需要上傳的檔案 上傳檔案的準備就不用多說了,先準備一個jsp頁面。此頁面中有一個form表單,此表單有如下三個特徵。 a、表單的method必須是post b、表單的enctyp
commons-fileupload實現檔案上傳、下載、線上開啟
最近做了一個檔案上傳、下載、與線上開啟檔案的功能,剛開始對檔案上傳的介面中含有其它表單(例如輸入框、密碼等)在上傳的過程中遇到了許多問題,下面我寫了一個同時實現檔案上傳、下載、線上開啟檔案的測試程式。 首先請看效果圖: 核心程式碼:
利用 Commons-Fileupload 實現檔案上傳
Apache FileUpload檔案上傳元件API解析(轉) Java Web開發人員可以使用Apache檔案上傳元件來接收瀏覽器上傳的檔案,該元件由多個類共同組成,但是,對於使用該元件來編寫檔案上傳功能的Java Web開發人員來說,只需要瞭解和使用其中的三個類:DiskFileUpload、FileIt
SpringMVC 通過commons-fileupload實現檔案上傳
[TOC](目錄) # 配置 ## web.xml ```xml ``` ## SpringMVC配置檔案 applicationContext.xml 上傳檔案的核心配置類:CommonsMultipartResolver,注意`id="multipartResolver"`不要寫錯 ```
Java架構-Spring mvc+oss儲存+fileupload多檔案上傳實現SSO單點登入模板管理
之前給大家介紹了sso的相關知識點和整合方案,考慮到每個系統所屬行業的不同,這邊針對於不同行業做了一些統一的sso單點登入介面模板,使用fileupload多檔案上傳+OSS阿里雲端儲存方案。 1. 阿里雲oss儲存Utils Java程式碼 2. 阿里雲配
框架中如何根據fileupload工具包實現檔案上傳功能
工具包 Apache-fileupload.jar – 檔案上傳核心包。 Apache-commons-io.jar – 這個包是fileupload的依賴包。同時又是一個工具包。 程式碼 servletFileUpload官方API /*獲取tomcat的wor
用socket自定義簡單協議實現檔案上傳與接受
一個上傳的資料包,主要包含檔案頭和檔案內容倆部分,主要按下面的格式,傳送: "File-Name:xxxxxx.zip;File-Type:exe;File-Length:1029292\r\n" ------檔案內容--------- 1、服務端的檔案接受服務 MySoc
檔案上傳控制元件Fileupload(實現檔案上傳並寫入資料庫)
首先我們來說一下Fileupload這個檔案上傳控制元件的幾大敗筆: 1.上傳之後按F5重新整理,重複提交 2.提交以後按後退鍵Fileupload中的資訊還在 3.不支援多檔案上傳 4.上傳前不能檢測檔案大小 解決方法: 1.建立iframe在子頁面實現或者重定向語句(R
用httpUrlConnection實現檔案上傳
1、事先了解 1.1 請求格式 我們使用http來上傳檔案,必須先了解http的請求格式,然後才好發報。主要分為以下四個部分: (1)分界符:由兩個連字元“--”和任意字串組成; (2)標準http報文格式,來形容上傳檔案的相關資訊,包括請求引數名,上傳檔名,檔案型別,接收
php 通過ssh2協議用sftp實現檔案上傳、下載
伺服器的連線 $connection=ssh2_connect($host, $port); if( ssh2_auth_pubkey_file($connection, $send_account,
common-fileUpload和 Spring中MultipartHttpServletRequest實現檔案上傳、以及過濾器的問題
遇到一個專案中寫的過濾器有些不明白為什麼那麼寫,其實就是以下的第二部分不理解造成的 二、 使用servlet時:多部件表單上傳對servlet取值問題 1) request.getParameter("..."),這個方法在表單為multiparty/form-d
用SmartUpload實現檔案上傳
首先要匯入SmartUpload.jar包 連結地址:http://pan.baidu.com/s/1eStyDZc 示例: index.jsp <body> <fo
commons.fileupload 文件上傳
session val sta ava 工廠 ota data 自定義 this 編輯jsp頁面獲取文件 1 <html> 2 <head> 3 <base href="<%=basePath%>"> 4
Spring MVC - MultipartFile實現檔案上傳(單檔案與多檔案上傳)
前提:引入jar包。 <dependency>
struts2實現檔案上傳與下載功能
一、Demo介紹 基於struts2框架,實現多檔案的上傳和下載功能。 實現原理圖: 部分介面圖: 上傳成功及下載頁面: 二、主要程式碼 uploadFile.jsp:在form表單中包含一個文字框(上傳使用者的姓名)和兩個檔案上傳選項. <%@
Java Springboot結合FastDFS實現檔案上傳以及根據圖片url將圖片上傳至圖片伺服器
上一篇文章我們已經講解了如何搭建FastDFS圖片伺服器,環境我們準備好了現在就讓我們開始與Java結合將他應用到實際的專案中吧。本篇文章我們將會展示上傳圖片到FastDFS圖片伺服器以及通過外網的圖片url將圖片上傳至我們自己的圖片伺服器中。 1.建立springbo
yii框架實現檔案上傳
yii框架實現檔案上傳 1.首先yii框架下載uploadFile類 2.html程式碼 <input type="file" class="file" style="display: none" name="business_license" /> 3.j
原生javascript實現檔案上傳功能程式碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ini