檔案上傳-java web
阿新 • • 發佈:2021-12-14
第一步:需要引入兩個依賴:common-fileupload和commin-io.
第二步.在web頁面中新增上傳檔案的輸入項
1.必須使用<input type="file">,並設定input的name屬性.
<input type="file" name="file">
2.form表單的enctype必須設定為multipart/form-data.
enctype="multipart/form-data"
3.form表單的提交方式必須是post.
method="post"
第三步.編寫servlet,將使用者上傳的資料儲存到本地硬碟.
1.判斷使用者提交的是否是帶檔案的表單,如果是普通的表單中止方法執行,直接返回.
if(!ServletFileUpload.isMultipartContent(request)){
return;
}
2.建立兩個路徑,一個檔案儲存的路徑,一個是檔案儲存的臨時路徑,防止檔案過大佔用硬碟空間.
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload"); File uploadFile = new File(uploadPath); if (!uploadFile.exists()){ uploadFile.mkdirs(); } String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp"); File file = new File(tmpPath); if (!file.exists()){ file.mkdirs(); }
3.建立一個DiskFileItempFactory物件,相當於是一個緩衝區,將過大的檔案放入臨時路徑.(將這個過程封裝成方法一,引數是:臨時路徑,返回DiskFileItempFactory物件)
DiskFileItemFactory factory = getDiskFileItemFactory(file);
4.建立並配置一個ServletFileUpload物件,需要用它來解析前端請求.(將這個過程封裝成方法二,引數是:DiskFileItempFactory物件,返回值:ServletFileUpload物件)
ServletFileUpload upload = getServletFileUpload(factory);
5.通過ServletFileUpload物件,將前端請求封裝成FileItem物件,FileItem物件可以獲取一個輸入流,將這個流輸出到本地磁碟上,就是使用者上傳的檔案(將這個過程封裝成方法三,引數是:ServletFileUpload物件,前端請求,檔案儲存路徑,返回值:執行結果)
String message = uploadParseRequest(upload, request, uploadPath);
6.根據執行結果對前端進行反饋,並跳轉頁面.
if (Objects.equals(message, "檔案上傳成功!")){
}else {
message = "請上傳檔案!";
}
request.setAttribute("message",message);
request.getRequestDispatcher("info.jsp").forward(request,response);
方法一
/**
* 上傳檔案的緩衝區
* @param file 臨時檔案路徑
* @return DiskFileItemFactory物件
*/
public static DiskFileItemFactory getDiskFileItemFactory(File file) {
//建立一個DiskFileItemFactory物件
DiskFileItemFactory factory = new DiskFileItemFactory();
//設定緩衝區大小為1M
factory.setSizeThreshold(1024 * 1024);
//設定臨時檔案的儲存路徑為方法引數中file
factory.setRepository(file);
//返回設定好的DiskFileItemFactory物件
return factory;
}
方法二
/**
* 對建立的ServletFileUpload物件進行配置
* @param factory 快取區
* @return 配置好的ServletFileUpload物件
*/
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
//建立ServletFileUpload物件,傳入設定好的快取區物件
ServletFileUpload upload = new ServletFileUpload(factory);
// 監聽上傳進度
upload.setProgressListener(new ProgressListener() {
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("總大小:" + pContentLength + "已上傳:" + pBytesRead+",進度:"+((double)pBytesRead/pContentLength)*100+"%");
}
});
// 處理編碼,防止亂碼
upload.setHeaderEncoding("UTF-8");
// 設定單個檔案的最大值
upload.setFileSizeMax(1024 * 1024 * 10);
//返回ServletFileUpload物件
return upload;
}
方法三(核心方法)
/**
* 將前端請求中的檔案寫入本地磁碟
* @param upload ServletFileUpload物件
* @param request 前端請求
* @param uploadPath 本地儲存檔案的路徑
* @return 執行結果
* @throws FileUploadException 檔案上傳異常
* @throws IOException IO異常
*/
public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath) throws FileUploadException, IOException {
//建立返回結果
String message = "";
//利用ServletFileUpload物件將前端請求解析並封裝成FileItem物件,返回一個FileItem物件集
List<FileItem> fileItems = upload.parseRequest(request);
//遍歷封裝後的FileItem物件
for (FileItem fileItem : fileItems) {
//判斷前端提交的表單有沒有檔案上傳
if (fileItem.isFormField()) { //沒有檔案上傳
//getFieldName獲取的的是前端表單控制元件的name;
String name = fileItem.getFieldName();
//處理亂碼
String value = fileItem.getString("UTF-8");
System.out.println(name + ": " + value);
} else {// 有檔案上傳
// ============處理檔名開始==============
// 拿到檔名
String uploadFileName = fileItem.getName();
System.out.println("上傳的檔名: " + uploadFileName);
//將檔名前後空格去除後,判斷是否為空字串
if (uploadFileName.trim().equals("")) {
continue;
}
// 獲取上傳的檔名,將路徑去除,只留下 / 後的字串就是檔案自己的名字 例如: C:\Users\lvjianhua\1.jpg
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
// 獲得檔案的字尾名,將最後一個點後面的字串獲取,來判斷檔案型別 例如: C:\Users\lvjianhua\1.jpg
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
//如果檔案字尾名fileExtName不是我們所需要的 就直按return.不處理,告訴使用者檔案型別不對。
System.out.println("檔案資訊[件名: " + fileName + " ---檔案型別" + fileExtName + "]");
// ================處理檔名完畢==============
// ==============處理存放地址開始==============
// 可以使用UID(唯一識別的通用碼),保證檔名唯一
// UUID.randomUUID(),這個方法可以隨機生一個唯一識別的通用碼;
String uuidPath = UUID.randomUUID().toString();
//用剛才隨機生成的UUID和檔案儲存的路徑拼接一個新路徑,這個路徑就是檔案最後儲存的路徑
String realPath = uploadPath + "/" + uuidPath;
//根據這個新路徑建立資料夾,每個檔案都會有一個單獨的資料夾,防止檔案重名,發生覆蓋,
File realPathFile = new File(realPath);
//判斷資料夾是否存在
if (!realPathFile.exists()) {
//不存在就生成一個
realPathFile.mkdir();
}
// ==============存放地址完畢==============
// =============檔案傳輸開始=============
//通過FileItem物件獲得檔案上傳的輸入流
InputStream is = fileItem.getInputStream();
//建立輸入流,檔案路徑就是,最終存放地址 + 檔名
FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
//建立一個緩衝區
byte[] buffer = new byte[1024 * 1024];
//設定一個int值,來儲存讀取資料的長度
int len = 0;
// 一邊讀,一邊寫,如果讀取的資料長度大於0說明還存在資料,就繼續輸出
while ((len = is.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
// 關閉流
fos.close();
is.close();
//執行到此處,說明檔案儲存成功,給返回結果賦值
message = "檔案上傳成功!";
//上傳成功,清除臨時檔案
fileItem.delete();
//=============檔案傳輸完畢=============
}
}
//返回執行結果
return message;
}
第四步.檢視本地磁碟中前端上傳的檔案
檔案上傳的四大注意事項:
- 為保證伺服器安全,上傳的檔案應該放在外界無法直接訪問的目錄下,比如放在WEB-INF目錄下
- 為防止上傳的檔案發生覆蓋,要為每一個上傳的檔案生成一個唯一的檔名
- 限制上傳檔案的大小
- 限制上傳檔案的型別,通過檔案的字尾名判斷是否合法