問題:JavaWeb中實(shí)現(xiàn)文件上傳的方式有哪些?
上回我們說了下文件下載的方式有哪些遵湖,這次我們從不同的環(huán)境下簡單來說說文件上傳的方式有哪些粱快。
文件上傳的方式
Servlet2.5 方式
Servlet3.0 方式
SpringMVC 方式
案例實(shí)操
Servlet2.5 方式
文件上傳涉及到前臺(tái)頁面的編寫和后臺(tái)服務(wù)器端代碼的編寫伸眶,前臺(tái)發(fā)送文件杨凑,后臺(tái)接收并保存文件,這才是一個(gè)完整的文件上傳晴楔。
1) 前臺(tái)頁面
在做文件上傳的時(shí)候顿苇,會(huì)有一個(gè)上傳文件的界面,首先我們需要一個(gè)表單税弃,并且表單的請(qǐng)求方式為 POST纪岁;其次我們的 form 表單的 enctype 必須設(shè)為”multipart/form-data”即 enctype="multipart/form-data" 意思是設(shè)置表單的 MIME 編碼。默認(rèn)情況下這個(gè)編碼格式是 ”application/x-www-form-urlencoded”则果,不能用于文件上傳幔翰;只有使用了 multipart/form-data 才能完整地傳遞文件數(shù)據(jù)漩氨。
<!DOCTYPE html>
<html>
<head>
<metacharset="UTF-8">
<title>上傳文件</title>
</head>
<body>
? ? <formaction="uploadServlet"method="post"enctype="multipart/form-data">
? ? ? ? 文件:<inputtype="file"name="myfile"/>
? ? ? ? <inputtype="submit"value="上傳"/>
? ? </form>
</body>
</html>
2) 后臺(tái) commons-fileupload 的使用
首先需要導(dǎo)入第三方j(luò)ar包,http://commons.apache.org/? 下載 commons-io 和 commons-fileupload 兩個(gè)jar的資源遗增。解壓并導(dǎo)入到項(xiàng)目中才菠。commons-fileupload.jar 是文件上傳的核心包 commons-io.jar 是 fileupload 的依賴包,同時(shí)又是一個(gè)工具包贡定。
介紹一下使用到的幾個(gè)核心類
??DiskFileItemFactory – 設(shè)置磁盤空間,保存臨時(shí)文件可都。只是一個(gè)工具類
??ServletFileUpload – 文件上傳的核心類缓待,此類接收 request,并解析
??ServletFileUpload.parseRequest(request); – List 解析 request
??1渠牲、創(chuàng)建一個(gè) DiskFileItemFactory 工廠類旋炒,并制定臨時(shí)文件和大小
??2、創(chuàng)建 ServletFileUpload 核心類签杈,接收臨時(shí)文件瘫镇,做請(qǐng)求的轉(zhuǎn)換
??3、通過 ServletFileUpload 類轉(zhuǎn)換原始請(qǐng)求答姥,得到 FileItem 集合
??4铣除、遍歷集合中的各個(gè)元素并處理
??5、判斷每個(gè)元素是否是普通表單項(xiàng)鹦付,如果是則按照普通表單項(xiàng)處理
??6尚粘、如果不是普通表單項(xiàng),則是文件敲长,通過處理的方式進(jìn)行處理(上傳)
publicclassUploadServletextendsHttpServlet{
? ? privatestaticfinallongserialVersionUID=1L;
?
? ? protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
? ? ? ? // 設(shè)定編碼郎嫁,可以獲取中文文件名
? ? ? ? request.setCharacterEncoding("UTF-8");
? ? ? ? // 獲取tomcat下的upload目錄的路徑
? ? ? ? Stringpath=getServletContext().getRealPath("/upload");
? ? ? ? // 臨時(shí)文件目錄
? ? ? ? StringtempPath=getServletContext().getRealPath("/temp");
? ? ? ? // 檢查我們是否有文件上傳請(qǐng)求
? ? ? ? // boolean isMultipart = ServletFileUpload.isMultipartContent(req);
? ? ? ? // 1、聲明DiskFileItemFactory工廠類祈噪,用于在指定磁盤上設(shè)置一個(gè)臨時(shí)目錄
? ? ? ? DiskFileItemFactorydisk=newDiskFileItemFactory(1024*10,newFile(tempPath));
? ? ? ? // 2泽铛、聲明ServletFileUpload,接收上面的臨時(shí)文件辑鲤。也可以默認(rèn)值
? ? ? ? ServletFileUploadup=newServletFileUpload(disk);
? ? ? ? // 3盔腔、解析request
? ? ? ? try{
? ? ? ? ? ? List<FileItem>list=up.parseRequest(request);
? ? ? ? ? ? if(list.size()>0) {
? ? ? ? ? ? ? ? for(FileItemfile:list) {
? ? ? ? ? ? ? ? ? ? // 判斷是否是普通的表單項(xiàng)
? ? ? ? ? ? ? ? ? ? if(file.isFormField()) {
? ? ? ? ? ? ? ? ? ? ? ? StringfieldName=file.getFieldName();
? ? ? ? ? ? ? ? ? ? ? ? // 中文亂碼,此時(shí)還需要指定獲取數(shù)據(jù)的編碼方式
? ? ? ? ? ? ? ? ? ? ? ? // String value = file.getString();
? ? ? ? ? ? ? ? ? ? ? ? Stringvalue=file.getString("UTF-8");
? ? ? ? ? ? ? ? ? ? ? ? System.out.println(fieldName+"="+value);
? ? ? ? ? ? ? ? ? ? }else{// 說明是一個(gè)文件
? ? ? ? ? ? ? ? ? ? ? ? // 獲取文件本身的名稱
? ? ? ? ? ? ? ? ? ? ? ? StringfileName=file.getName();
? ? ? ? ? ? ? ? ? ? ? ? System.out.println(file.getFieldName());
? ? ? ? ? ? ? ? ? ? ? ? // 處理文件名稱
? ? ? ? ? ? ? ? ? ? ? ? fileName=fileName.substring(fileName.lastIndexOf("\\")+1);
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("old Name : "+fileName);
? ? ? ? ? ? ? ? ? ? ? ? // 修改名稱
? ? ? ? ? ? ? ? ? ? ? ? StringextName=fileName.substring(fileName.lastIndexOf("."));
? ? ? ? ? ? ? ? ? ? ? ? StringnewName=UUID.randomUUID().toString().replace("-","")+extName;
? ? ? ? ? ? ? ? ? ? ? ? // 保存新的名稱遂填,并寫出到新文件中
? ? ? ? ? ? ? ? ? ? ? ? file.write(newFile(path+"/"+newName));
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("文件名是:"+fileName);
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("文件大小是:"+file.getSize());
? ? ? ? ? ? ? ? ? ? ? ? file.delete();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }catch(FileUploadExceptione) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }catch(Exceptione) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
?
}
Servlet3.0 方式
使用注解 @MultipartConfig 將一個(gè) Servlet 標(biāo)識(shí)為支持文件上傳铲觉。Servlet3.0 將 multipart/form-data 的 POST 請(qǐng)求封裝成 Part,通過 Part 對(duì)上傳的文件進(jìn)行操作吓坚。
前臺(tái)
<!DOCTYPE html>
<html>
<head>
<metacharset="UTF-8">
<title>上傳文件</title>
</head>
<body>
? ? <formaction="upload"method="post"enctype="multipart/form-data">
? ? ? ? 姓名:<inputtype="text"name="uname"/>
? ? ? ? 文件:<inputtype="file"name="myfile"/>
? ? ? ? <inputtype="submit"value="上傳"/>
? ? </form>
</body>
</html>
后臺(tái)
@WebServlet("/upload")
@MultipartConfig
publicclassUploadServletextendsHttpServlet{
? ? privatestaticfinallongserialVersionUID=1L;
?
? ? protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
? ? ? ? System.out.println("上傳文件...");
? ? ? ? // 設(shè)置編碼
? ? ? ? request.setCharacterEncoding("UTF-8");
? ? ? ? // 獲取普通表單項(xiàng)參數(shù)
? ? ? ? Stringuname=request.getParameter("uname");
? ? ? ? System.out.println(uname);
? ? ? ? // 上傳文件
? ? ? ? // 得到part對(duì)象 request.getpart(name):name代表的是表單中file元素的name屬性值
? ? ? ? Partpart=request.getPart("myfile");
? ? ? ? // 得到文件存放的路徑
? ? ? ? Stringpath=request.getServletContext().getRealPath("/");
? ? ? ? // 得到文件名
? ? ? ? StringfileName=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
<beanid="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
?
<propertyname="maxUploadSize">
?
<value>104857600</value>
?
</property>
?
<propertyname="maxInMemorySize">
?
<value>4096</value>
?
</property>
?
</bean>
FileController
importjava.io.File;
?
importjava.io.IOException;
?
importjavax.servlet.http.HttpServletRequest;
?
importorg.springframework.stereotype.Controller;
?
importorg.springframework.web.bind.annotation.RequestMapping;
?
importorg.springframework.web.multipart.MultipartFile;
?
importorg.springframework.web.multipart.MultipartHttpServletRequest;
?
importorg.springframework.web.servlet.ModelAndView;
?
@Controller
?
publicclassFileController{
?
@RequestMapping("/uploadFile")
?
publicModelAndViewuploadFile(HttpServletRequestrequest){
?
ModelAndViewmv=newModelAndView();
?
mv.setViewName("result");
?
MultipartHttpServletRequestmr=(MultipartHttpServletRequest)request;
?
MultipartFilemultipartFile=mr.getFile("file");
?
Stringpath=request.getSession().getServletContext().getRealPath("upload");
?
System.out.println(path);
?
if(null!=multipartFile&&!multipartFile.isEmpty()){
?
? ? StringfileName=multipartFile.getOriginalFilename();
?
try{
?
? ? multipartFile.transferTo(newFile(path,fileName));
?
? ? mv.addObject("msg","文件上傳成功!");
?
}catch(Exceptione) {
?
? ? mv.addObject("msg","上傳失敗!");
?
? ? e.printStackTrace();
?
? ? ?? }
?
? ? ?? }
?
returnmv;
?
? ? }
?
}
前臺(tái)表單
<formaction="uploadFile"method="post"enctype="multipart/form-data">
?
? ? <inputtype="file"name="file"/>
?
? ? <buttontype="submit">提交</button>
?
</form>
擴(kuò)展~MIME
MIME(Multipurpose Internet Mail Extensions)多用途互聯(lián)網(wǎng)郵件擴(kuò)展類型撵幽。是設(shè)定某種擴(kuò)展名的文件用一種應(yīng)用程序來打開的方式類型,當(dāng)該擴(kuò)展名文件被訪問的時(shí)候礁击,瀏覽器會(huì)自動(dòng)使用指定應(yīng)用程序來打開盐杂。多用于指定一些客戶端自定義的文件名逗载,以及一些媒體文件打開方式。
它是一個(gè)互聯(lián)網(wǎng)標(biāo)準(zhǔn)链烈,擴(kuò)展了電子郵件標(biāo)準(zhǔn)厉斟,使其能夠支持:
非ASCII字符文本;非文本格式附件(二進(jìn)制强衡、聲音擦秽、圖像等);由多部分(multiple parts)組成的消息體漩勤;包含非ASCII字符的頭信息(Header information)感挥。
這個(gè)標(biāo)準(zhǔn)被定義在RFC 2045、RFC 2046越败、RFC 2047触幼、RFC 2048、RFC 2049等RFC中究飞。 MIME改善了由RFC 822轉(zhuǎn)變而來的RFC 2822置谦,這些舊標(biāo)準(zhǔn)規(guī)定電子郵件標(biāo)準(zhǔn)并不允許在郵件消息中使用7位ASCII字符集以外的字符。正因如此亿傅,一些非英語字符消息和二進(jìn)制文件媒峡,圖像,聲音等非文字消息原本都不能在電子郵件中傳輸(MIME可以)葵擎。MIME規(guī)定了用于表示各種各樣的數(shù)據(jù)類型的符號(hào)化方法丝蹭。 此外,在萬維網(wǎng)中使用的HTTP協(xié)議中也使用了MIME的框架坪蚁,標(biāo)準(zhǔn)被擴(kuò)展為互聯(lián)網(wǎng)媒體類型奔穿。
查看不同文件對(duì)應(yīng)的 MIME 類型,推薦大家一種方式敏晤,以 Tomcat為例贱田,它下面的 web.xml 文件可以查看所有的MIME類型,通過 Ctrl + F 搜索快速找到你想知道的文件對(duì)應(yīng)的 MIME 類型嘴脾。