本篇博客將講解的是Springmvc的文件上傳和下載功能。對於上傳功能,我們在項目中是經常會用到的,比如用戶注冊的時候,上傳用戶頭像,這個時候就會使用到上傳的功能。而對於下載,使用場景也很常見,比如我們項目中有個使用說明是是pdf版的,會提供給用戶進行下載的功能。相對於來說,這兩個功能都是很常見,廢話不多說,按照慣例,我們先來看一下本篇博客的目錄。
目錄
一:搭建SpringMvc開發環境
二:實現文件上傳的功能
三:將上傳文件綁定到具體的對象上
四 : 實現用戶下載的功能
五:總結
一:搭建Springmvc開發環境
首先我們在myeclipse中,新建一個web項目,名為:SpringMvcFileUpload.然后導入必要的jar包,這里的jar包主要是Spring的jar包還有另外一個很重要的jar包,名稱為:commons-fileupload-1.3.1.jar,這個是apache開發的一個專門用來上傳文件的工具包,其中預置了很多的文件上傳的api供我們使用,然后在src目錄下新建一個包,名為com.wyq.Controller和com.wyq.domain。兩個包分別用來存放控制器和領域模型。然后在webRoot目錄下新建Folder,取名jsp,主要用來存放我們的jsp頁面,接下來配置web.xml文件,在其中配置上我們的Springmv的控制分發器Servlet用於處理客戶端請求的鏈接,然后新建一個Springmvc-config文件,主要是配置Springmvc的bean,這里除了需要配置視圖解析器用來解析視圖資源和基本的掃描包之外,還需要配置一個很重要的bean,該bean的名字是“multiPartResolver”,主要是用來處理文件的,其中可以配置的屬性為上傳文件的大小和編碼,我們來具體看一下配置文件的代碼:
web.xml文件:
<!--Springmvc的控制分發器-->
<servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
springmvc-config.xml:
<context:component-scan base-package="com.wyq" /> <!-- 配置視圖解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/page/"></property> <property name="suffix" value=".jsp"></property> </bean> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--上傳文件的最大大小> <property name="maxUploadSize" value="17367648787"></property>
<!-- 上傳文件的編碼 -->
<property name="defaultEncoding" value="UTF-8"></property>
</bean>
二:實現文件上傳的功能
2.1:首先我們來新建一個jsp頁面,命名為:uploadform.jsp寫一個上傳的頁面form表單,其中一定要注意的是在表單的屬性中添加entcypt="multipart/form-data",這表示上傳的將會是二進制流的格式,以規定的二進制進行上傳,便於服務器處理,使用post請求:
<body> <form action="gotoAction" enctype="multipart/form-data" method="post"> <table> <tr> <td>請選擇文件:</td> <td><input type="file" name="file"></td> </tr> <tr> <td>開始上傳</td> <td><input type="submit" value="上傳"></td> </tr> </table> </form> </body>
2.2:再寫一個上傳成功的jsp頁面,主要是用來當上傳成功時候跳轉的頁面,命名為:success.jsp
<body> <h2>文件上傳成功!</h2> </body>
2.3:然后再寫一個上傳失敗的頁面,主要是用來當上傳失敗的時候跳轉的頁面,命名為:error.jsp
<body> <h2>文件上傳失敗!請檢查文件是否存在</h2> </body>
2.4:寫好了jsp頁面,接下來就是寫我們的控制器了,Springmvc控制器,在我們的com.wyq.Controller中寫一個FileUploadController類,然后寫上具體的代碼,如下所示,注意其中使用MultipartFile來接受form表單傳過來的file文件,MultipartFile有幾個核心的api,可以供我們使用,比如 boolean isEmpty(),用來判斷文件是否為空。void transferTo( File file),把文件寫入目標路徑地址.
@Controller public class FileUploadController { @RequestMapping(value="/{formName}") public String loginForm(@PathVariable String formName){ return formName; } @RequestMapping(value="/gotoAction",method=RequestMethod.POST) public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request){ if (!file.isEmpty()) { String contextPath = request.getContextPath();//"/SpringMvcFileUpload" String servletPath = request.getServletPath();//"/gotoAction" String scheme = request.getScheme();//"http" String storePath= "E:\\project\\SpringMvcFileUpload\\WebRoot\\images";//存放我們上傳的文件路徑 String fileName = file.getOriginalFilename(); File filepath = new File(storePath, fileName); if (!filepath.getParentFile().exists()) { filepath.getParentFile().mkdirs();//如果目錄不存在,創建目錄 } try { file.transferTo(new File(storePath+File.separator+fileName));//把文件寫入目標文件地址 } catch (Exception e) { e.printStackTrace(); return "error"; } return "success";//返回到成功頁面 }else { return "error";//返回到失敗的頁面 } }
2.5:好了,到此我們就可以實現上傳功能了,發布在Tomact容器里,然后就可以進行上傳文件了。在瀏覽中輸入:http://localhost:8080/SpringMvcFileUpload/uploadForm具體的頁面請求如下,然后瀏覽具體的文件,點擊上傳按鈕:
選擇好了文件,點擊上傳
到了這一步還沒完,我們再往下看,有沒有寫入目標文件夾,也就是在D:\userUploadFile\Files目錄下看是否存在我的上傳文件,查看是存在的也就是正確寫入了
三:將上傳文件綁定到具體的對象上
3.1:首先我們來定義一個實體類User,這個實體類中的headimage屬性的主要作用就是用來映射我們上傳的文件,可以看到它是MultipartFile類型的:
public class User implements Serializable{//用戶實體類 private String userName; private MultipartFile headimage;//上傳文件會自動綁定到該屬性 //省略getter和setter方法 }
3.2:然后寫我們的 jsp上傳頁面,這里我們來模擬一個用戶注冊上傳頭像的場景,新建一個registerForm.jsp頁面,然后寫一個form表單,如下:
<body> <h2>用戶注冊</h2> <form action="register" enctype="multipart/form-data" method="post"> <table> <tr> <td>用戶頭像:</td> <td><input type="file" name="headimage"></td> </tr> <tr> <td>上傳:</td> <td><input type="submit" value="上傳"></td> </tr> </table> </form> </body>
3.3:寫我們的方法控制器處理注冊邏輯的層的代碼,注意其中的user對象加入了@ModelAttribute注解,其主要作用是用來映射把上面的form表單的headimage屬性自動注入到對象里面,還有Map<String,Object> map主要是為了存放user對象,放在requestScope里面,這樣就可用el表達式把其中的值取出來了。
@RequestMapping(value="/register",method=RequestMethod.POST) public String reg(@ModelAttribute User user,HttpServletRequest request,Map<String,Object> map){ final String wrong="error"; final String good="success"; MultipartFile headimage = user.getHeadimage(); boolean empty = headimage.isEmpty(); if (!empty) { String realPath = request.getServletContext().getRealPath("/images"); String uploadPath="D:\\userUploadFile\\Files"; String headimageName = headimage.getOriginalFilename(); File imageFile = new File(uploadPath,headimageName); try { headimage.transferTo(new File(uploadPath+File.separator+headimageName)); } catch (Exception e) { e.printStackTrace(); return wrong; } map.put("user", user); return "userInfo"; }else { return wrong; } }
3.4:我們來新建一個jsp頁面,取名為userinfo.jsp,其主要作用是顯示剛才的我們的文件名:
<body>
用戶頭像:${requestScope.user.headimage.originalFilename}
</body>
3.5:頁面寫完了,我們在來模擬測試一下,在客戶端Ie瀏覽器中,輸入http://localhost:8080/SpringMvcFileUpload/registerForm:
四:實現用戶下載的功能
4.1:首先我們來改造一下剛才的userInfo.jsp頁面,主要目的是為了把它變成一個下載的連接,然后用我們就可以寫我們的控制器用來處理href的請求來了。其中可以看到我們使用了el表達式把url傳遞給下一個控制器,控制器可以取出這些值進行處理:
<body> <h3>文件下載</h3> --> <a href="download?filename=${requestScope.user.headimage.originalFilename}"> 用戶頭像:${requestScope.user.headimage.originalFilename} </a> </body>
4.2:來看看我們的download控制器代碼:注意download方法返回的是ResponseEntity<byte[]> 類型,這個是封裝好的返回類型,我們需要傳入byte數組、headers、HttpStatus,然后它就會返回具體的下載流,調用客戶端去下載資源
@RequestMapping(value="/download",method=RequestMethod.GET) //匹配的是href中的download請求 public ResponseEntity<byte[]> download(HttpServletRequest request,@RequestParam("filename") String filename, Model model) throws IOException{ String downloadFilePath="D:\\userUploadFile\\Files";//從我們的上傳文件夾中去取 File file = new File(downloadFilePath+File.separator+filename);//新建一個文件 HttpHeaders headers = new HttpHeaders();//http頭信息 String downloadFileName = new String(filename.getBytes("UTF-8"),"iso-8859-1");//設置編碼 headers.setContentDispositionFormData("attachment", downloadFileName); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); //MediaType:互聯網媒介類型 contentType:具體請求中的媒體類型信息 return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED); }
4.3:我們來測試一下寫的東西是否能准確運行,點擊超鏈接,注意此鏈接指向的地址:http://localhost:8080/SpringMvcFileUpload/download?filename="myheadimage".jpg,這就表示這個鏈接會去請求控制器,然后控制器進行處理下載, 這樣就完成了文件的下載功能了:
點擊超鏈接:
五:總結
本篇博文介紹了SpringMvc上傳和文件的功能,需要注意的地方就是對於文件上傳包common-fileupload.jar包的使用,還有在配置文件上配置mulitipartResolver這個bean。下面又介紹了用java 實體類去映射上傳文件的屬性對應的文件,這點的好處就是它會自動映射,然后把對象放入到我們的請求域中,就可以展示給界面用戶層,這也是mvc思想模式的體現。接下來是介紹去下載文件,只需要從我們的寫入的目標地址去取出文件,再進行responseEntity對象的封裝,就可以實現下載功能
參考資料
《spring+mybatis企業應用實戰》