在樂位元組學習的第三天

weixin_53403536發表於2020-12-09

問題:JavaWeb中實現檔案上傳的方式有哪些?

上回我們說了下檔案下載的方式有哪些,這次我們從不同的環境下簡單來說說檔案上傳的方式有哪些。

檔案上傳的方式

  • Servlet2.5 方式
  • Servlet3.0 方式
  • SpringMVC 方式

案例實操

Servlet2.5 方式

檔案上傳涉及到前臺頁面的編寫和後臺伺服器端程式碼的編寫,前臺傳送檔案,後臺接收並儲存檔案,這才是一個完整的檔案上傳。

1) 前臺頁面

在做檔案上傳的時候,會有一個上傳檔案的介面,首先我們需要一個表單,並且表單的請求方式為 POST;其次我們的 form 表單的 enctype 必須設為”multipart/form-data”即 enctype=“multipart/form-data” 意思是設定表單的 MIME 編碼。預設情況下這個編碼格式是 ”application/x-www-form-urlencoded”,不能用於檔案上傳;只有使用了 multipart/form-data 才能完整地傳遞檔案資料。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>上傳檔案</title>
</head>
<body>
	<form action="uploadServlet" method="post" enctype="multipart/form-data">
		檔案:<input type="file" name="myfile"/>
		<input type="submit" value="上傳" />
	</form>
</body>
</html>

2) 後臺 commons-fileupload 的使用

首先需要匯入第三方jar包,http://commons.apache.org/ 下載 commons-io 和 commons-fileupload 兩個jar的資源。解壓並匯入到專案中。commons-fileupload.jar 是檔案上傳的核心包 commons-io.jar 是 fileupload 的依賴包,同時又是一個工具包。

介紹一下使用到的幾個核心類

  DiskFileItemFactory – 設定磁碟空間,儲存臨時檔案。只是一個工具類

  ServletFileUpload – 檔案上傳的核心類,此類接收 request,並解析

  ServletFileUpload.parseRequest(request); – List 解析 request

  1、建立一個 DiskFileItemFactory 工廠類,並制定臨時檔案和大小

  2、建立 ServletFileUpload 核心類,接收臨時檔案,做請求的轉換

  3、通過 ServletFileUpload 類轉換原始請求,得到 FileItem 集合

  4、遍歷集合中的各個元素並處理

  5、判斷每個元素是否是普通表單項,如果是則按照普通表單項處理

  6、如果不是普通表單項,則是檔案,通過處理的方式進行處理(上傳)

public class UploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 設定編碼,可以獲取中文檔名
		request.setCharacterEncoding("UTF-8");
		// 獲取tomcat下的upload目錄的路徑
		String path = getServletContext().getRealPath("/upload");
		// 臨時檔案目錄
		String tempPath = getServletContext().getRealPath("/temp");
		// 檢查我們是否有檔案上傳請求
		// boolean isMultipart = ServletFileUpload.isMultipartContent(req);
		// 1、宣告DiskFileItemFactory工廠類,用於在指定磁碟上設定一個臨時目錄
		DiskFileItemFactory disk = new DiskFileItemFactory(1024 * 10, new File(tempPath));
		// 2、宣告ServletFileUpload,接收上面的臨時檔案。也可以預設值
		ServletFileUpload up = new ServletFileUpload(disk);
		// 3、解析request
		try {
			List<FileItem> list = up.parseRequest(request);
			if (list.size() > 0) {
				for (FileItem file : list) {
					// 判斷是否是普通的表單項
					if (file.isFormField()) {
						String fieldName = file.getFieldName();
						// 中文亂碼,此時還需要指定獲取資料的編碼方式
						// String value = file.getString();
						String value = file.getString("UTF-8");
						System.out.println(fieldName + "=" + value);
					} else { // 說明是一個檔案
						// 獲取檔案本身的名稱
						String fileName = file.getName();
						System.out.println(file.getFieldName());
						// 處理檔名稱
						fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
						System.out.println("old Name : " + fileName);
						// 修改名稱
						String extName = fileName.substring(fileName.lastIndexOf("."));
						String newName = UUID.randomUUID().toString().replace("-", "") + extName;
						// 儲存新的名稱,並寫出到新檔案中
						file.write(new File(path + "/" + newName));
						System.out.println("檔名是:" + fileName);
						System.out.println("檔案大小是:" + file.getSize());
						file.delete();
					}
				}
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

Servlet3.0 方式

使用註解 @MultipartConfig 將一個 Servlet 標識為支援檔案上傳。Servlet3.0 將 multipart/form-data 的 POST 請求封裝成 Part,通過 Part 對上傳的檔案進行操作。

前臺

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>上傳檔案</title>
</head>
<body>
	<form action="upload" method="post" enctype="multipart/form-data">
		姓名:<input type="text" name="uname"/>
		檔案:<input type="file" name="myfile"/>
		<input type="submit" value="上傳" />
	</form>
</body>
</html>

後臺

@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("上傳檔案...");
		// 設定編碼
		request.setCharacterEncoding("UTF-8");
		// 獲取普通表單項引數
		String uname = request.getParameter("uname");
		System.out.println(uname);
		// 上傳檔案
		// 得到part物件 request.getpart(name):name代表的是表單中file元素的name屬性值
		Part part = request.getPart("myfile");
		// 得到檔案存放的路徑
		String path = request.getServletContext().getRealPath("/");
		// 得到檔名
		String fileName = part.getSubmittedFileName();
		// 上傳
		part.write(path + fileName);
	}

}

SpringMVC 方式

Pom 檔案修改 新增 commons-fileupload 依賴

<dependency> 

    <groupId>commons-fileupload</groupId> 

    <artifactId>commons-fileupload</artifactId> 

    <version>1.3.2</version> 

</dependency> 

servlet-context.xml

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

    <property name="maxUploadSize"> 

    <value>104857600</value> 

    </property> 

    <property name="maxInMemorySize"> 

    <value>4096</value> 

    </property> 

</bean> 

FileController

import java.io.File; 

import java.io.IOException; 

import javax.servlet.http.HttpServletRequest; 

import org.springframework.stereotype.Controller; 

import org.springframework.web.bind.annotation.RequestMapping; 

import org.springframework.web.multipart.MultipartFile; 

import org.springframework.web.multipart.MultipartHttpServletRequest; 

import org.springframework.web.servlet.ModelAndView; 

@Controller 

public class FileController { 

    @RequestMapping("/uploadFile") 

    public ModelAndView uploadFile(HttpServletRequest request){ 

        ModelAndView mv=new ModelAndView(); 

        mv.setViewName("result"); 

        MultipartHttpServletRequest mr=(MultipartHttpServletRequest) request; 

        MultipartFile multipartFile= mr.getFile("file"); 

        String path=request.getSession().getServletContext().getRealPath("upload"); 

        System.out.println(path); 

        if(null!=multipartFile&&!multipartFile.isEmpty()){ 

        	String fileName=multipartFile.getOriginalFilename(); 

        try { 

        	multipartFile.transferTo(new File(path,fileName)); 

        	mv.addObject("msg", "檔案上傳成功!"); 

        } catch (Exception e) { 

        	mv.addObject("msg", "上傳失敗!"); 

        	e.printStackTrace(); 

        } 

        } 

        return mv; 

	} 

} 

前臺表單

<form action="uploadFile" method="post" enctype="multipart/form-data"> 

	<input type="file" name="file"/> 

	<button type="submit"> 提交</button> 

</form> 

擴充套件~MIME

MIME(Multipurpose Internet Mail Extensions)多用途網際網路郵件擴充套件型別。是設定某種副檔名的檔案用一種應用程式來開啟的方式型別,當該副檔名檔案被訪問的時候,瀏覽器會自動使用指定應用程式來開啟。多用於指定一些客戶端自定義的檔名,以及一些媒體檔案開啟方式。

它是一個網際網路標準,擴充套件了電子郵件標準,使其能夠支援:

非ASCII字元文字;非文字格式附件(二進位制、聲音、影像等);由多部分(multiple parts)組成的訊息體;包含非ASCII字元的頭資訊(Header information)。

這個標準被定義在RFC 2045、RFC 2046、RFC 2047、RFC 2048、RFC 2049等RFC中。 MIME改善了由RFC 822轉變而來的RFC 2822,這些舊標準規定電子郵件標準並不允許在郵件訊息中使用7位ASCII字符集以外的字元。正因如此,一些非英語字元訊息和二進位制檔案,影像,聲音等非文字訊息原本都不能在電子郵件中傳輸(MIME可以)。MIME規定了用於表示各種各樣的資料型別的符號化方法。 此外,在全球資訊網中使用的HTTP協議中也使用了MIME的框架,標準被擴充套件為網際網路媒體型別。

檢視不同檔案對應的 MIME 型別,推薦大家一種方式,以 Tomcat為例,它下面的 web.xml 檔案可以檢視所有的MIME型別,通過 Ctrl + F 搜尋快速找到你想知道的檔案對應的 MIME 型別。

。 MIME改善了由RFC 822轉變而來的RFC 2822,這些舊標準規定電子郵件標準並不允許在郵件訊息中使用7位ASCII字符集以外的字元。正因如此,一些非英語字元訊息和二進位制檔案,影像,聲音等非文字訊息原本都不能在電子郵件中傳輸(MIME可以)。MIME規定了用於表示各種各樣的資料型別的符號化方法。 此外,在全球資訊網中使用的HTTP協議中也使用了MIME的框架,標準被擴充套件為網際網路媒體型別。

檢視不同檔案對應的 MIME 型別,推薦大家一種方式,以 Tomcat為例,它下面的 web.xml 檔案可以檢視所有的MIME型別,通過 Ctrl + F 搜尋快速找到你想知道的檔案對應的 MIME 型別。

相關文章