檔案上傳下載—servlet API實現
阿新 • • 發佈:2019-02-04
servlet API實現檔案上傳下載需要的jar包:
UploadServlet.java
package com.ymw.web.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
/**
* @ClassName: UploadHandleServlet
* @Description: TODO
* @author: lmb
*
*/
public class UploadHandleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 得到上傳檔案的儲存目錄,將上傳的檔案存放於WEB-INF目錄下,不允許外界直接訪問,保證上傳檔案的安全
String savePath = this.getServletContext().getRealPath("/images");
// 上傳時生成的臨時檔案儲存目錄
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tmpFile = new File(tempPath);
if (!tmpFile.exists()) {
// 建立臨時目錄
tmpFile.mkdir();
}
// 訊息提示
String message = "";
try {
// 使用Apache檔案上傳元件處理檔案上傳步驟:
// 1、建立一個DiskFileItemFactory工廠
DiskFileItemFactory factory = new DiskFileItemFactory();
// 設定工廠的緩衝區的大小,當上傳的檔案大小超過緩衝區的大小時,就會生成一個臨時檔案存放到指定的臨時目錄當中。
factory.setSizeThreshold(1024 * 100);// 設定緩衝區的大小為100KB,如果不指定,那麼緩衝區的大小預設是10KB
// 設定上傳時生成的臨時檔案的儲存目錄
factory.setRepository(tmpFile);
// 2、建立一個檔案上傳解析器
ServletFileUpload upload = new ServletFileUpload(factory);
// 監聽檔案上傳進度
upload.setProgressListener(new ProgressListener() {
public void update(long pBytesRead, long pContentLength,
int arg2) {
System.out.println("檔案大小為:" + pContentLength + ",當前已處理:"
+ pBytesRead);
/**
* 檔案大小為:14608,當前已處理:4096 檔案大小為:14608,當前已處理:7367
* 檔案大小為:14608,當前已處理:11419 檔案大小為:14608,當前已處理:14608
*/
}
});
// 解決上傳檔名的中文亂碼
upload.setHeaderEncoding("UTF-8");
// 3、判斷提交上來的資料是否是上傳表單的資料
if (!ServletFileUpload.isMultipartContent(request)) {
// 按照傳統方式獲取資料
return;
}
// 設定上傳單個檔案的大小的最大值,目前是設定為1024*1024位元組,也就是1MB
upload.setFileSizeMax(1024 * 1024);
// 設定上傳檔案總量的最大值,最大值=同時上傳的多個檔案的大小的最大值的和,目前設定為10MB
upload.setSizeMax(1024 * 1024 * 10);
// 4、使用ServletFileUpload解析器解析上傳資料,解析結果返回的是一個List<FileItem>集合,每一個FileItem對應一個Form表單的輸入項
List<FileItem> list = upload.parseRequest(request);
for (FileItem item : list) {
// 如果fileitem中封裝的是普通輸入項的資料
if (item.isFormField()) {
String name = item.getFieldName();
// 解決普通輸入項的資料的中文亂碼問題
String value = item.getString("UTF-8");
// value = new String(value.getBytes("iso8859-1"),"UTF-8");
System.out.println(name + "=" + value);
} else {// 如果fileitem中封裝的是上傳檔案
// 得到上傳的檔名稱,
String filename = item.getName();
System.out.println(filename);
request.setAttribute("filename", filename);
if (filename == null || filename.trim().equals("")) {
continue;
}
// 注意:不同的瀏覽器提交的檔名是不一樣的,有些瀏覽器提交上來的檔名是帶有路徑的,如:
// c:\a\b\1.txt,而有些只是單純的檔名,如:1.txt
// 處理獲取到的上傳檔案的檔名的路徑部分,只保留檔名部分
filename = filename
.substring(filename.lastIndexOf("\\") + 1);
// 得到上傳檔案的副檔名
String fileExtName = filename.substring(filename
.lastIndexOf(".") + 1);
// 如果需要限制上傳的檔案型別,那麼可以通過檔案的副檔名來判斷上傳的檔案型別是否合法
System.out.println("上傳的檔案的副檔名是:" + fileExtName);
// 獲取item中的上傳檔案的輸入流
InputStream in = item.getInputStream();
// 得到檔案儲存的名稱
String saveFilename = makeFileName(filename);
// 得到檔案的儲存目錄
String realSavePath = makePath(saveFilename, savePath);
// 建立一個檔案輸出流
FileOutputStream out = new FileOutputStream(realSavePath
+ "\\" + saveFilename);
// 建立一個緩衝區
byte buffer[] = new byte[1024];
// 判斷輸入流中的資料是否已經讀完的標識
int len = 0;
// 迴圈將輸入流讀入到緩衝區當中,(len=in.read(buffer))>0就表示in裡面還有資料
while ((len = in.read(buffer)) > 0) {
// 使用FileOutputStream輸出流將緩衝區的資料寫入到指定的目錄(savePath + "\\"
// + filename)當中
out.write(buffer, 0, len);
}
// 關閉輸入流
in.close();
// 關閉輸出流
out.close();
// 刪除處理檔案上傳時生成的臨時檔案
// item.delete();
message = "檔案上傳成功!";
}
}
} catch (FileUploadBase.FileSizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message", "單個檔案超出最大值!!!");
request.getRequestDispatcher("/addproduct.jsp").forward(request,
response);
return;
} catch (FileUploadBase.SizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message", "上傳檔案的總的大小超出限制的最大值!!!");
request.getRequestDispatcher("/addproduct.jsp").forward(request,
response);
return;
} catch (Exception e) {
message = "檔案上傳失敗!";
e.printStackTrace();
}
request.setAttribute("message", message);
request.getRequestDispatcher("/addproduct.jsp").forward(request,
response);
}
/**
* @Method: makeFileName
* @Description: 生成上傳檔案的檔名,檔名以:uuid+"_"+檔案的原始名稱
* @Anthor:lmb
* @param filename
* 檔案的原始名稱
* @return uuid+"_"+檔案的原始名稱
*/
private String makeFileName(String filename) { // 2.jpg
// 為防止檔案覆蓋的現象發生,要為上傳檔案產生一個唯一的檔名
return UUID.randomUUID().toString() + "_" + filename;
}
/**
* 為防止一個目錄下面出現太多檔案,要使用hash演算法打散儲存
*
* @Method: makePath
* @Description:
* @Anthor:lmb
*
* @param filename
* 檔名,要根據檔名生成儲存目錄
* @param savePath
* 檔案儲存路徑
* @return 新的儲存目錄
*/
private String makePath(String filename, String savePath) {
// 得到檔名的hashCode的值,得到的就是filename這個字串物件在記憶體中的地址
int hashcode = filename.hashCode();
int dir1 = hashcode & 0xf; // 0--15
int dir2 = (hashcode & 0xf0) >> 4; // 0-15
// 構造新的儲存目錄
String dir = savePath + "\\" + dir1 + "\\" + dir2; // upload\2\3
// upload\3\5
// File既可以代表檔案也可以代表目錄
File file = new File(dir);
// 如果目錄不存在
if (!file.exists()) {
// 建立目錄
file.mkdirs();
}
return dir;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
upload.jsp(在該頁面進行檔案上傳)
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>檔案上傳</title>
</head>
<body>
<form action="upload.do" enctype="multipart/form-data" method="post">
<h2>請選擇您需要上傳的圖片:</h2>
<input type="file" name="file1"><br><br>
<input type="submit" value="提交">
</form>
</body>
</html>
web.xml中的配置:
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>com.ymw.web.servlet.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/upload.do</url-pattern>
</servlet-mapping>
uploadResult.jsp(在該頁面顯示上傳結果)
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>uploadResult page</title>
</head>
<body>
${ message }
<br/><br/>
檔案路徑:/images/${filename }
</body>
</html>
注意:
要想在前臺頁面獲得filename和message,後臺的上傳處理中一定要有
request.setAttribute("filename", filename);
request.setAttribute("message", message);