JavaEE組件commons-fileupload完成文件上傳、下載。本站提示廣大學習愛好者:(JavaEE組件commons-fileupload完成文件上傳、下載)文章只能為提供參考,不一定能成為您想要的結果。以下是JavaEE組件commons-fileupload完成文件上傳、下載正文
1、文件上傳概述
完成Web開辟中的文件上傳功效,須要兩步操作:
1、在Web頁面中添加上傳輸出項
<form action="#" method="post" enctype="multipart/form-data">
<input type="file" name="filename1"/><br>
<input type="file" name="filename2"/><br>
<input type="submit" value="上傳"/>
<form>
<!-- 1、表雙方式必需是post
2、必需設置encType屬性為 multipart/form-data.設置該值後,閱讀器在上傳文件時,將會把文件數據附帶在http要求新聞體中,
並應用MIME協定對上傳的文件停止描寫,以便利吸收方對上傳數據停止解析和處置。
3、必需要設置input的name屬性,不然閱讀器將不會發奉上傳文件的數據。
-->
2、在Servlet中讀取文件上傳數據,並保留到辦事器硬盤
Request對象供給了一個getInputStream辦法,經由過程這個辦法可以讀取到客戶端提交過去的數據。但因為用戶能夠會同時上傳多個文件,在Servlet端編程直接讀取上傳數據,並分離解析出響應的文件數據是一項異常費事的任務。
好比上面是截取的閱讀器上傳文件時發送的要求的HTTP協定中的部門內容:
Accept-Language: zh-Hans-CN,zh-Hans;q=0.5 Content-Type: multipart/form-data; boundary=---------------------------7dfa01d1908a4 UA-CPU: AMD64 Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko Content-Length: 653 Host: localhost:8080 Connection: Keep-Alive Pragma: no-cache Cookie: JSESSIONID=11CEFF8E271AB62CE676B5A87B746B5F -----------------------------7dfa01d1908a4 Content-Disposition: form-data; name="username" zhangsan -----------------------------7dfa01d1908a4 Content-Disposition: form-data; name="userpass" 1234 -----------------------------7dfa01d1908a4 Content-Disposition: form-data; name="filename1"; filename="C:\Users\ASUS\Desktop\upload.txt" Content-Type: text/plain this is first file content! -----------------------------7dfa01d1908a4 Content-Disposition: form-data; name="filename1"; filename="C:\Users\ASUS\Desktop\upload2.txt" Content-Type: text/plain this is Second file content! hello -----------------------------7dfa01d1908a4--
從下面的數據中也能夠看出,假如本身手工的去朋分讀取數據很難寫出硬朗穩固的法式。所以,為便利用戶處置上傳數據,Apache開源組織供給了一個用來處置表單文件上傳的一個開源組件(Commons-fileupload),該組件機能優良,而且其API應用極端簡略,可讓開辟人員輕松完成web文件上傳功效,是以在web開辟中完成文件上傳功效,平日應用Commons-fileupload組件完成。
須要導入兩個jar包:Commons-fileupload、commons-io
response.setContentType("text/html;charset=utf-8");//設置呼應編碼
request.setCharacterEncoding("utf-8");
PrintWriter writer = response.getWriter();//獲得呼應輸入流
ServletInputStream inputStream = request.getInputStream();//獲得要求輸出流
/*
* 1、創立DiskFileItemFactory對象,設置緩沖區年夜小和暫時文件目次
* 該類有兩個結構辦法一個是無參的結構辦法,
* 另外一個是帶兩個參數的結構辦法
* @param int sizeThreshold,該參數設置內存緩沖區的年夜小,默許值為10K。當上傳文件年夜於緩沖區年夜小時,fileupload組件將應用暫時文件緩存上傳文件
* @param java.io.File repository,該參數指定暫時文件目次,默許值為System.getProperty("java.io.tmpdir");
*
* 假如應用了無參的結構辦法,則應用setSizeThreshold(int sizeThreshold),setRepository(java.io.File repository)
* 辦法手動停止設置
*/
DiskFileItemFactory factory = new DiskFileItemFactory();
int sizeThreshold=1024*1024;
factory.setSizeThreshold(sizeThreshold);
File repository = new File(request.getSession().getServletContext().getRealPath("temp"));
// System.out.println(request.getSession().getServletContext().getRealPath("temp"));
// System.out.println(request.getRealPath("temp"));
factory.setRepository(repository);
/*
* 2、應用DiskFileItemFactory對象創立ServletFileUpload對象,並設置上傳文件的年夜小
*
* ServletFileUpload對象擔任處置上傳的文件數據,並將表單中每一個輸出項封裝成一個FileItem
* 該對象的經常使用辦法有:
* boolean isMultipartContent(request);斷定上傳表單能否為multipart/form-data類型
* List parseRequest(request);解析request對象,並把表單中的每個輸出項包裝成一個fileItem 對象,並前往一個保留了一切FileItem的list聚集
* void setFileSizeMax(long filesizeMax);設置單個上傳文件的最年夜值
* void setSizeMax(long sizeMax);設置上傳溫江總量的最年夜值
* void setHeaderEncoding();設置編碼格局,處理上傳文件名亂碼成績
*/
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("utf-8");//設置編碼格局,處理上傳文件名亂碼成績
/*
* 3、挪用ServletFileUpload.parseRequest辦法解析request對象,獲得一個保留了一切上傳內容的List對象
*/
List<FileItem> parseRequest=null;
try {
parseRequest = upload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
/*
* 4、對list停止迭代,每迭代一個FileItem對象,挪用其isFormField辦法斷定能否是文件上傳
* true表現是通俗表單字段,則挪用getFieldName、getString辦法獲得字段名和字段值
* false為上傳文件,則挪用getInputStream辦法獲得數據輸出流,從而讀取上傳數據
*
* FileItem用來表現文件上傳表單中的一個上傳文件對象或許通俗的表單對象
* 該對象經常使用辦法有:
* boolean isFormField();斷定FileItem是一個文件上傳對象照樣通俗表單對象
* true表現是通俗表單字段,
* 則挪用getFieldName、getString辦法獲得字段名和字段值
* false為上傳文件,
* 則挪用getName()取得上傳文件的文件名,留意:有些閱讀器會攜帶客戶端途徑,須要本身減除
* 挪用getInputStream()辦法獲得數據輸出流,從而讀取上傳數據
* delete(); 表現在封閉FileItem輸出流後,刪除暫時文件。
*/
for (FileItem fileItem : parseRequest) {
if (fileItem.isFormField()) {//表現通俗字段
if ("username".equals(fileItem.getFieldName())) {
String username = fileItem.getString();
writer.write("您的用戶名:"+username+"<br>");
}
if ("userpass".equals(fileItem.getFieldName())) {
String userpass = fileItem.getString();
writer.write("您的暗碼:"+userpass+"<br>");
}
}else {//表現是上傳的文件
//分歧閱讀器上傳的文件能夠帶有途徑名,須要本身切割
String clientName = fileItem.getName();
String filename = "";
if (clientName.contains("\\")) {//假如包括"\"表現是一個領路徑的名字,則截取最初的文件名
filename = clientName.substring(clientName.lastIndexOf("\\")).substring(1);
}else {
filename = clientName;
}
UUID randomUUID = UUID.randomUUID();//生成一個128位長的全球獨一標識
filename = randomUUID.toString()+filename;
/*
* 設計一個目次生成算法,假如所用用戶上傳的文件總數是億數目級的或更多,放在統一個目次下回招致文件索引異常慢,
* 所以,設計一個目次構造來疏散寄存文件長短常有需要,且公道的
* 將UUID取哈希算法,散列到更小的規模,
* 將UUID的hashcode轉換為一個8位的8進制字符串,
* 從這個字符串的第一名開端,每個字符代表一級目次,如許就構建了一個八級目次,每級目次中最多有16個子目次
* 這不管關於辦事器照樣操作體系都長短常高效的目次構造
*/
int hashUUID =randomUUID.hashCode();
String hexUUID = Integer.toHexString(hashUUID);
//System.out.println(hexUUID);
//獲得將上傳的文件存存儲在哪一個文件夾下的相對途徑
String filepath=request.getSession().getServletContext().getRealPath("upload");
for (char c : hexUUID.toCharArray()) {
filepath = filepath+"/"+c;
}
//假如目次不存在就生成八級目次
File filepathFile = new File(filepath);
if (!filepathFile.exists()) {
filepathFile.mkdirs();
}
//從Request輸出流中讀取文件,並寫入到辦事器
InputStream inputStream2 = fileItem.getInputStream();
//在辦事器端創立文件
File file = new File(filepath+"/"+filename);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] buffer = new byte[10*1024];
int len = 0;
while ((len= inputStream2.read(buffer, 0, 10*1024))!=-1) {
bos.write(buffer, 0, len);
}
writer.write("您上傳文件"+clientName+"勝利<br>");
//封閉資本
bos.close();
inputStream2.close();
}
}
//留意Eclipse的上傳的文件是保留在項目標運轉目次,而不是workspace中的工程目次裡。
2、文件上傳須要特殊留意的成績: (這些成績在下面的代碼中都供給了簡略的處理)
1、文件寄存的地位
為包管辦事器的平安,上傳文件應保留在運用法式的WEB-INF目次下,或許不受WEB辦事器治理的目次,假如用戶上傳一個帶有可履行代碼的文件,如jsp文件,依據拼接拜訪途徑去拜訪的話,可以在辦事器端做任何工作。
2、為避免多用戶上傳形同文件名的文件,而招致文件籠罩的情形產生,文件上傳法式應包管上傳文件具有獨一文件名。
應用UUID + 用戶上傳文件名的方法重定名
關於UUID:
UUID(Universally Unique Identifier)全局獨一標識符,是指在一台機械上生成的數字,它包管對在統一時空中的一切機械都是獨一的。依照開放軟件基金會(OSF)制訂的尺度盤算,用到了以太網卡地址、納秒級時光、芯片ID碼和很多能夠的數字。由以下幾部門的組合:以後日期和時光(UUID的第一個部門與時光有關,假如你在生成一個UUID以後,過幾秒又生成一個UUID,則第一個部門分歧,其他雷同),時鐘序列,全局獨一的IEEE機械辨認號(假如有網卡,從網卡取得,沒有網卡以其他方法取得),UUID的獨一缺點在於生成的成果串會比擬長。
是一個128位長的數字,普通用16進制表現。算法的焦點思惟是聯合機械的網卡、本地時光、一個隨即數來生成GUID。從實際上講,假如一台機械每秒發生10000000個GUID,則可以包管(幾率意義上)3240年不反復。
從JDK1.5開端,生成UUID釀成了一件簡略的事,認為JDK完成了UUID:
java.util.UUID,直接挪用便可.
UUID uuid = UUID.randomUUID();
String s = UUID.randomUUID().toString();//用來生成數據庫的主鍵id異常不錯。。
UUID是由一個十六位的數字構成,表示出來的情勢例如
550E8400-E29B-11D4-A716-446655440000
3、為避免單個目次下文件過量,影響文件讀寫速度,處置上傳文件的法式應當應依據能夠的上傳總量,選擇適合的目次構造生成算法,將上傳文件疏散存儲。如應用hashcode辦法構建多級目次。
4、假如分歧用戶都上傳了雷同的文件,那末在辦事器端沒有需要存儲統一個文件的許多分拷貝,如許很糟蹋資本,應當設盤算法處理這類反復文件的成績。
5、JSP技巧道理主動完成了多線程。所以開辟者不須要斟酌上傳文件的多線程操作
3、文件下載
<%
ArrayList<String> fileNames = new ArrayList<String>();
fileNames.add("file/aa.txt");
fileNames.add("file/bb.jpg");
for(String fileName : fileNames) {
%>
<form action="DownloadServlet" method="get">
<input type="hidden" name="fileName" value="<%=fileName %>" />
<input type="submit" value="下載:<%=fileName %>" />
</form>
<%
}
%>
request.setCharacterEncoding("utf-8");
String filename = request.getParameter("fileName");
String urlname = URLEncoder.encode(filename, "utf-8");//避免文件名中有中文亂碼
response.setHeader("Content-Disposition","attachment;filename="+urlname);
FileInputStream fis = new FileInputStream(new File(request.getSession().getServletContext().getRealPath(filename)));
BufferedInputStream bis = new BufferedInputStream(fis);
ServletOutputStream sos = response.getOutputStream();
byte[] buffer = new byte[1024];
int len=0;
while((len=bis.read(buffer, 0, 1024))!=-1){
sos.write(buffer, 0, len);
}
bis.close();
fis.close();
4、在SSH中應用smartUpload組件簡化文件上傳下載
以上就是本文的全體內容,願望對年夜家的進修有所贊助,也願望年夜家多多支撐。