日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

SpingMVC框架:fileUpload组件原理和实现

發(fā)布時間:2024/7/5 c/c++ 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpingMVC框架:fileUpload组件原理和实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

QUESTION:fileUpload組件原理和實現(xiàn)

?

ANSWER:

?

目錄

QUESTION:fileUpload組件原理和實現(xiàn)

ANSWER:

一:異常產(chǎn)生

查詢了一系列博客后,發(fā)現(xiàn)這是由于上傳文件的大小超過了可以上傳的臨時文件限制。

二:fileUpload組件及Java Web中文件上傳的原理方法

2.1基本原理

2.2實現(xiàn)代碼

2.3重要方法

2.4注意事項:


?

一:異常產(chǎn)生

在剛學習springMVC框架時,上傳文件出現(xiàn)了以下HTTP Status 500 – Internal Server Error:

Exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. C:\Program Files\apache-tomcat-8.5.38\temp\upload_2f146db1_be01_4311_a3d8_e6c7cd69c8d3_00000002.tmp (拒絕訪問。)org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)javax.servlet.http.HttpServlet.service(HttpServlet.java:661)org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)javax.servlet.http.HttpServlet.service(HttpServlet.java:742)org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

Root Cause

org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. C:\Program Files\apache-tomcat-8.5.38\temp\upload_2f146db1_be01_4311_a3d8_e6c7cd69c8d3_00000002.tmp (拒絕訪問。)org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:351)org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115)com.xy.controller.UserController.fileUpload(UserController.java:36)sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)java.lang.reflect.Method.invoke(Method.java:498)org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)javax.servlet.http.HttpServlet.service(HttpServlet.java:661)org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)javax.servlet.http.HttpServlet.service(HttpServlet.java:742)org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

Root Cause

java.io.FileNotFoundException: C:\Program Files\apache-tomcat-8.5.38\temp\upload_2f146db1_be01_4311_a3d8_e6c7cd69c8d3_00000002.tmp (拒絕訪問。)java.io.FileOutputStream.open0(Native Method)java.io.FileOutputStream.open(FileOutputStream.java:270)java.io.FileOutputStream.<init>(FileOutputStream.java:213)java.io.FileOutputStream.<init>(FileOutputStream.java:162)org.apache.commons.io.output.DeferredFileOutputStream.thresholdReached(DeferredFileOutputStream.java:178)org.apache.commons.io.output.ThresholdingOutputStream.checkThreshold(ThresholdingOutputStream.java:224)org.apache.commons.io.output.ThresholdingOutputStream.write(ThresholdingOutputStream.java:128)org.apache.commons.fileupload.util.Streams.copy(Streams.java:107)org.apache.commons.fileupload.util.Streams.copy(Streams.java:70)org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:347)org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115)com.xy.controller.UserController.fileUpload(UserController.java:36)sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)java.lang.reflect.Method.invoke(Method.java:498)org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)javax.servlet.http.HttpServlet.service(HttpServlet.java:661)org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)javax.servlet.http.HttpServlet.service(HttpServlet.java:742)org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

Note The full stack trace of the root cause is available in the server logs.

查詢了一系列博客后,發(fā)現(xiàn)這是由于上傳文件的大小超過了可以上傳的臨時文件限制。

?

二:fileUpload組件及Java Web中文件上傳的原理方法

2.1基本原理

給出官網(wǎng)文檔:upLoad。

組件FileUpload依賴于Commons IO組件,因此在繼續(xù)之前,要確保在你的工程classpath中有描述頁中提到的相應版本。(這里FileUpload版本為:commons- fileupload-1.2.1,Commons IO版本為:commons-io-1.4)。

最簡單的示例(官網(wǎng)):

// Create a factory for disk-based file items DiskFileItemFactory factory = new DiskFileItemFactory();// Configure a repository (to ensure a secure temp location is used) ServletContext servletContext = this.getServletConfig().getServletContext(); File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir"); factory.setRepository(repository);// Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory);// Parse the request List<FileItem> items = upload.parseRequest(request);

原理:

上傳的文件要求包括一個根據(jù)RFC 1867(在HTML中基于表單的文件)編碼的選項列表清單。組件FileUpload可以解析這個請求,并給你的應用程序提供一份獨立上傳的項目清單。無論每個項目背后如何執(zhí)行都實現(xiàn)了FileItem接口。

這里將描述組件FileUpload庫的普通API,這些API比較簡單。不過,對于最終的實現(xiàn),你可以參考最新的API流。

每一個文件項目都有一些屬性,這些可能在你的應用程序中應用到。比如:每一個項目有一個名稱name和內(nèi)容類型content type,并提供了一個 InputStream訪問其數(shù)據(jù)。另一方面,你處理項目的方法可能有所不同,這個依賴于是否這個項目是一個規(guī)則的表單域,即:這個數(shù)據(jù)是來自普通的表單文本,還是普通的HTML域或是一個上傳文件。在FileItem接口中提供了處理這些問題的方法,可以更加方便的去訪問這些數(shù)據(jù)。

組件FileUpload使用FileItemFactory工廠創(chuàng)建新的文件項目。這個給了組件FileUpload很大的靈活性。這個工廠擁有怎樣創(chuàng)建項目的最終控制權。工廠執(zhí)行過程中上傳項目文件的臨時數(shù)據(jù)可以存儲在內(nèi)存中或硬盤上。這個依賴于上傳項目的大小(即:數(shù)據(jù)的字節(jié))。不過這種行為可以在你的應用程序中適當?shù)淖远ㄖ啤?/p>

解析:

在實現(xiàn)上傳項目之前,當然需要解析這個請求。確保這個請求的確是一個正確的上傳文件,組件FileUpload為了使這個判斷簡單,提供了一個靜態(tài)的方法去做這個事情。

// 檢測我們是否一個文件上傳的請求

boolean isMultipart = ServletFileUpload.isMultipartContent(request);

示例:

最簡單的使用情況如下:

* 上傳項目只要足夠小,就應該將其保存在內(nèi)存中。

* 較大的項目應該被寫入到硬盤的臨時文件中。

* 應該避免有非常大的上傳項目。

* 設置項目默認的在內(nèi)存中所占的空間,限制最大的上傳請求,并設定臨時文件 的位置。

處理這種情況下的請求非常的簡單:

// 創(chuàng)建磁盤工廠

FileItemFactory factory = new DiskFileItemFactory();

// 創(chuàng)建處理工具

ServletFileUpload upload = new ServletFileUpload(factory);

// 解析

List <FileItem> items = upload.parseRequest(request);

這就是我們真正需要的全部代碼。

處理的結果是生成了一個文件項目列表,每個文件項目實現(xiàn)一個FileItem接口。下面將介紹如何處理這些項目。

?

控制:

如果你的使用情況和上面描述的例子很接近,但是你需要在一點更多的控制限定文件的大小或臨時文件的存放位置。你可以很容易的自定義上傳實例或文件項目或兩者的行為。下面例子展示了幾種配置選項:

// 創(chuàng)建磁盤工廠

DiskFileItemFactory factory = new DiskFileItemFactory();

// 設置參數(shù)

factory.setSizeThreshold(yourMaxMemorySize);

factory.setRepository(yourTempDirectory);

// 創(chuàng)建處理工具

ServletFileUpload upload = new ServletFileUpload(factory);

// 設置最大允許的尺寸

upload.setSizeMax(yourMaxRequestSize);

// 解析

List <FileItem> items = upload.parseRequest(request);

當然,每一個配置處理方法都是獨立于其他方法的,但是如果你想一次性配置這個工廠,你可以使用工廠的另一個重載方法。像這樣:

DiskFileItemFactory factory = new DiskFileItemFactory( yourMaxMemorySize, yourTempDirectory);

詳細的接口文檔:http://commons.apache.org/proper/commons-fileupload/javadocs/api-release/index.html

2.2實現(xiàn)代碼

使用fileUpload固定步驟:

? ? 創(chuàng)建工廠類:DiskFileItemFactory factory=new DiskFileItemFactory();
? ? 創(chuàng)建解析器:ServletFileUpload upload=new ServletFileUpload(factory);
? ? 使用解析器解析request對象:List<FileItem> list=upload.parseRequest(request);

?

首先導入相關包。見上文。

1.jsp代碼:

<%--Created by IntelliJ IDEA.User: 楊路恒Date: 2019/8/17 0017Time: 11:24 --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>文件上傳</title> </head> <body><form action="UserController/fileUpload1" method="post" enctype="multipart/form-data">選擇文件:<input type="file" name="upload"><br>上傳:<input type="submit" value="上傳" name="uploadFile"></form> </body> </html>

2.配置springmvc-xml:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--掃描spring的包--><context:component-scan base-package="com.xy"></context:component-scan><!--視圖解析器對象--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"><property name="prefix" value="/WEB-INF/pages/"></property><property name="suffix" value=".jsp"></property></bean><!--前端控制器,哪些靜態(tài)資源不攔截--><mvc:resources location="/css/" mapping="/css/**"/> <!-- 樣式 --><mvc:resources location="/images/" mapping="/images/**"/> <!-- 圖片 --><mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript --><!--開啟springMVC的支持,類型轉(zhuǎn)換器生效--><mvc:annotation-driven></mvc:annotation-driven></beans>

3.配置web.xml:

<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--前端控制器--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-mvc.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!--中文亂碼過濾器--><filter><filter-name>characterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping> </web-app>

4.控制器代碼:

package com.xy.controller;import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest; import java.io.File; import java.util.List;@Controller @RequestMapping("/UserController") public class UserController {/*** 文件上傳* @return*/@RequestMapping("/fileUpload1")public String fileUpload(HttpServletRequest request) throws Exception {System.out.println("文件上傳");//使用fileupload組件上傳文件//上傳路徑String path=request.getSession().getServletContext().getRealPath("/uploads");//判斷該路徑是否存在File file=new File(path);if (!file.exists()){file.mkdirs();}//解析request對象獲取上傳文件項DiskFileItemFactory diskFileItemFactory=new DiskFileItemFactory(); // diskFileItemFactory.setSizeThreshold(1024*1024); //設置內(nèi)存緩沖區(qū)大小,系統(tǒng)默認值10KBFile temp=new File(request.getSession().getServletContext().getRealPath("/temp"));temp.mkdirs();System.out.println("建立成功");diskFileItemFactory.setRepository(temp);System.out.println(System.getProperty("java.io.tmpdir"));ServletFileUpload servletFileUpload=new ServletFileUpload(diskFileItemFactory);servletFileUpload.setFileSizeMax(100*1024*1024);//解析requestList<FileItem> items=servletFileUpload.parseRequest(request);for (FileItem item:items) {//判斷當前item是否是上傳文件對象if (item.isFormField()){//說明普通表單向}else {//說明上傳文件項//獲取文件名稱String fileName=item.getName();//完成文件上傳item.write(new File(path,fileName));System.out.println("寫入成功");//刪除臨時文件,系統(tǒng)會自動刪除 // item.delete();}}return "success";} }

5.success代碼:

<%--Created by IntelliJ IDEA.User: 楊路恒Date: 2019/8/17 0017Time: 11:21 --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>Title</title> </head> <body><h1>文件上傳成功</h1> </body> </html>

1.普通表單提交默認enctype="application/x-www-form-urlencoded";但是當表單中存在文件類型時,需要設置enctype="multipart/form-data",它不對字符進行編碼,用于發(fā)送二進制的文件(即所有文件類型,如視頻、圖片、音樂、文檔都可以用此類型entype);還有一種enctype="text/plain"用于發(fā)送純文本內(nèi)容。

2.表單請求方式必須為post。

3.接收時不能再用request.getParameter(),而是request.getInputStream()解析二進制流,得到ServletInputStream對象。
?

2.3重要方法

1.DiskFileItemFactory:

DiskFileItemFactory有兩個方法 :setSizeThreshold和setRepository

?setRepository方法用于設置當上傳文件尺寸大于setSizeThreshold方法設置的臨界值時,將文件以臨時文件形式保存在磁盤上的存放目錄。有一個對應的獲得臨時文件夾的 File getRespository() 方法。
? ? ? ? 注意:當從沒有調(diào)用此方法設置臨時文件存儲目錄時,默認采用系統(tǒng)默認的臨時文件路徑,可以通過系統(tǒng)屬性 java.io.tmpdir 獲取。如下代碼:
System.getProperty("java.io.tmpdir");
Tomcat系統(tǒng)默認臨時目錄為“<tomcat安裝目錄>/temp/”。
?setSizeThreshold方法說明:
??
?Apache文件上傳組件在解析上傳數(shù)據(jù)中的每個字段內(nèi)容時,需要臨時保存解析出的數(shù)據(jù),以便在后面進行數(shù)據(jù)的進一步處理(保存在磁盤特定位置或插入數(shù)據(jù)庫)。因為Java虛擬機默認可以使用的內(nèi)存空間是有限的,超出限制時將會拋出“java.lang.OutOfMemoryError”錯誤。如果上傳的文件很大,例如800M的文件,在內(nèi)存中將無法臨時保存該文件內(nèi)容,Apache文件上傳組件轉(zhuǎn)而采用臨時文件來保存這些數(shù)據(jù);但如果上傳的文件很小,例如600個字節(jié)的文件,顯然將其直接保存在內(nèi)存中性能會更加好些。
? ? ? ?setSizeThreshold方法用于設置是否將上傳文件已臨時文件的形式保存在磁盤的臨界值(以字節(jié)為單位的int值),如果從沒有調(diào)用該方法設置此臨界值,將會采用系統(tǒng)默認值10KB。對應的getSizeThreshold() 方法用來獲取此臨界值。

2.FileItem:

? ? String getFieldName():獲取表單項的name的屬性值。
? ? String getName():獲取文件字段的文件名。如果是普通字段,則返回null
? ? String getString():獲取字段的內(nèi)容。如果是普通字段,則是它的value值;如果是文件字段,則是文件內(nèi)容。
? ? String getContentType():獲取上傳的文件類型,例如text/plain、image。如果是普通字段,則返回null。
? ? long getSize():獲取字段內(nèi)容的大小,單位是字節(jié)。
? ? boolean isFormField():判斷是否是普通表單字段,若是,返回true,否則返回false。
? ? InputStream getInputStream():獲得文件內(nèi)容的輸入流。如果是普通字段,則返回value值的輸入流。

2.4注意事項:

1.文件名中文亂碼處理:servletFileUpload.setHeaderEncoding("utf-8") 或 request.setCharacterEncoding("utf-8");
2.表單普通字段中文亂碼處理:new String(str.getBytes("iso-8859-1","utf-8"));
3.設置內(nèi)存緩沖區(qū)的大小,默認為10KB:diskFileItemFactory.setSizeThreshold(1024*1024);
4.指定臨時文件目錄,如果單個文件的大小超過內(nèi)存緩沖區(qū),該文件將會臨時緩存在此目錄下diskFileItemFactory.setRepository(file);
5.設置單個文件大小限制,如果有某個文件超過此大小,將拋出FileUploadBase.FileSizeLimitExceededException:servletFileUpload.setFileSizeMax(1024*1024*10);
6.設置所有文件,也就是請求大小限制,如果文件總和超過此大小,將拋出FileUploadBase.SizeLimitExceededException:servletFileUpload.setSizeMax(1024*1024*20);
7.利用UUID生成偽隨機字符串作為文件名避免重復:UUID.randomUUID().toString();
8.將文件寫到硬盤上。寫完之后,系統(tǒng)會自動將放在臨時文件目錄的該文件刪除:fileItem.write(new File(path,fileName));
?

fileUpload用來上傳文件,主要任務解析request:

parseRequest(request)

?

總結

以上是生活随笔為你收集整理的SpingMVC框架:fileUpload组件原理和实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。