Spring 文件上传(一)
这一节主要总结一下,ssm项目中配置CommonsMultipartResolver
来完成前端文件上传的功能。
环境配置
**jar
**包
CommonsMultipartResolver
主要用到了以下几个jar包:
commons-fileupload
:这是Apache Commons FileUpload库的jar包,提供了文件上传的功能,CommonsMultipartResolver
使用了这个库来解析文件上传请求。
commons-io
:这是Apache Commons IO库的jar包,提供了一些IO操作的工具类,CommonsMultipartResolver
可能会用到这些工具类来处理上传的文件数据。
这些jar包为CommonsMultipartResolver
提供了文件上传所需的基本功能和支持,使得它能够有效地处理文件上传请求。
1 2 3 4 5 6 7 8 9 10 11 12
| <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.8.0</version> </dependency> </dependencies>
|
CommonsMultipartResolver
主要做了什么
CommonsMultipartResolver
是 Spring 框架中用于处理文件上传的解析器。它的主要作用包括以下几点:
- 解析文件上传请求:
CommonsMultipartResolver
用于解析客户端提交的包含文件上传的请求。它能够从请求中提取出上传的文件数据,并将其封装成 MultipartFile
对象,方便后续处理。
- 设置文件上传属性:通过配置
CommonsMultipartResolver
,你可以设置一些文件上传的属性,比如最大上传文件大小、编码格式等。这些属性可以帮助你限制文件大小、指定编码方式等。
- 处理文件上传异常:
CommonsMultipartResolver
还能够处理文件上传过程中可能出现的异常,比如文件大小超出限制等。它可以帮助你捕获这些异常并进行适当的处理。
总的来说,CommonsMultipartResolver
在 Spring MVC 中起到了解析和处理文件上传请求的作用,让你能够方便地处理客户端提交的文件数据。
配置CommonsMultipartResolver
1 2 3 4 5
|
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
|
上传到本地
前端代码
在ajax
中,我们使用FormData
封装数据,类似我们的form
表单提交之后的效果。这样的话我们下面的Controller
就可以正常接到了。要注意ajax
需要带上的两个参数是processData:false, contentType:false
。
在Ajax
请求中, processData
和 contentType
都是用来处理发送的数据的参数。
processData
是一个布尔值,用于指示 jQuery
是否应该转换发送的数据。如果设置为 false
,则不会将数据转换为查询字符串格式。这在发送FormData
对象或者其他不希望被转换的数据时非常有用。
contentType
是用来设置请求头中的 Content-Type
字段的值。它指定了发送数据的类型。当发送的数据是 FormData
对象或者文件时, contentType
应该被设置为 false
,以便让浏览器自动识别并设置正确的 Content-Type
。
总的来说, processData
和 contentType
都是用来控制发送数据的格式和类型,特别是在处理 FormData
对象和文件上传时非常有用。
processData
是一个布尔值,用于指示 jQuery
是否应该转换发送的数据。如果设置为 true
,则会将数据转换为查询字符串格式。这意味着,如果你发送的是一个对象,它会被转换成类似 key1=value1&key2=value2
的形式,以便作为 URL
的一部分发送到服务器。这在发送简单的键值对数据时非常有用。对于POST
请求,如果 processData
设置为 true
,数据将被转换为查询字符串格式并作为请求的正文内容发送到服务器。这通常用于将简单的键值对数据发送给服务器。但是,如果你发送的是 FormData
对象或者希望发送的数据不被转换,你应该将 processData
设置为 false
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <script src="./js/jquery.min.js"></script> <script> let showPic = ()=>{ let file = $("#file_input")[0].files[0]; let formdata = new FormData(); formdata.set("file",file) $.ajax({ type:"post", processData:false, contentType:false, url:"http://localhost:8080/file_upload_ssm_war_exploded/upload_file", data: formdata, success(resp){ console.log(resp); } }); }; </script> <style type="text/css"> .imgFile{ width: 200px; height: 200px; } </style> </head> <body> <h2>Hello World!</h2>
<form action="login"> 用户名:<input name="username"><br> 密码:<input name="password"><br> 头像:<br> <img class="imgFile" src="js:javascript(0)" ><br> <input id="file_input" type="file" name="file" onchange="showPic()"> <button class="upload-button">上传图片</button><br> </form> </body> </html>
|
后端代码
以下代码将我们的文件存储到了本地项目upload
文件下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @ResponseBody @RequestMapping("/upload_file") public Map<String,String> test(MultipartFile file,String abv,HttpServletRequest req) throws IOException { String realPath = req.getServletContext().getRealPath("/upload");
File dir = new File(realPath); System.out.println(abv); if(!dir.exists()){ dir.mkdirs(); } String fileName = UUID.randomUUID().toString(); String originalName = file.getOriginalFilename(); File file1 = new File(dir,fileName.concat(originalName.substring(originalName.lastIndexOf(".")))); file.transferTo(file1); Map<String,String> map = new HashMap<>(); map.put("success","yes"); return map; }
|
为了解决我们的请求乱码,我们需要配置一个前端的字符过滤器,并且配置强制编码,不然配置会失效的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <filter> <filter-name>encFilter</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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
存储结果

上传到远程的tomcat
服务器
更改端口
首先我们需要了解,从tomcat配置文件中,我们可以看出,在启动tomcat的时候默认启动了3个端口,分别是8080(8443)、8009、8005。
8080(8443)端口
1 2 3 4 5 6
| <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" maxParameterCount="1000" />
|
这个应该是我们最熟悉的一个,平常开发测试也经常用,该Connector
用于监听浏览器发送的请求,设置为80后可以直接使用http://localhost
访问。http
协议,其中redirectPort
表示如果发送的是https
请求,就将请求发送到8443端口。8443是默认的https
监听端口,默认是没有开启的,如果要开启由于tomcat
不自带证书所以除了取消注释之外,还需要自己生成证书并指定。
8009端口
Nginx
、Apache
等反向代理tomcat
时就可以使用ajp
协议反向代理到该端口。虽然我们经常使用http
反向代理到8080端口,但由于ajp
建立tcp
链接后一般长时间保持,从而减少Http
反复进行tcp
链接和断开的开销,所以反向代理中ajp
是比http高效的。
8005端口
1
| <Server port="8005" shutdown="SHUTDOWN">
|
tomcat
监听的关闭端口,就是说这个端口负责监听关闭tomcat
的请求。当执行shutdown.sh
关闭tomcat
就是链接8005端口执行SHUTDOWN
命令;由此,我们直接用telnet
向8005端口执行SHUTDOWN
来关闭tomcat
,这也是比较正统的关闭方式,如果这个端口没被监听,那么sh
脚本就是无效的。
从上面的介绍可以知道,我们开发的时候,tomcat
使用的主要还是8080端口和8005端口,我们如果需要在开启一个图片服务器就需要更改这几个端口。
server.xml


更改只读属性
更改我们tomcat
中web.xml
的initparam
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param>
<init-param> <param-name>readonly</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
|
创建对应上传目录
webapps下创建一个upload目录
导入依赖
这里我们使用了jersey-client
的包,我们可以了解jersey-client客户端。这其实就是一个支持RestFull
的client
框架。
1 2 3 4 5
| <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.19</version> </dependency>
|
前端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <script src="./js/jquery.min.js"></script> <script> let showPic = ()=> { let file = $("#file_input")[0].files[0]; let formdata = new FormData(); formdata.set("file", file) formdata.set("abv", "斯大林快回家") $.ajax({ type: "post", processData: false, contentType: false, url: "http://localhost:8080/file_upload_ssm_war_exploded/upload_file", data: formdata, success(resp) { $(".imgFile").attr("src",resp.url); console.log(resp.message); } });
}; </script> <style type="text/css"> .imgFile{ width: 200px; height: 200px; } </style> </head> <body> <h2>Hello World!</h2>
<form action="login"> 用户名:<input name="username"><br> 密码:<input name="password"><br> 头像:<br> <img class="imgFile" src="js:javascript(0)" ><br> <input id="file_input" type="file" name="file" onchange="showPic()">
<button class="upload-button">上传图片</button><br>
<%-- <input type="submit" /><br>--%>
</form> </body> </html>
|
后端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| package com.zgy.file.controller;
import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.WebResource; import com.zgy.file.service.FileService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.UUID;
@Controller public class UploadController { public String ServerUrl = "http://127.0.0.1:8090/upload/"; @ResponseBody @RequestMapping("/upload_file") public Map<String,String> test(MultipartFile file,String abv,HttpServletRequest req) throws IOException { HashMap<String,String> map = new HashMap<>(); String originalName = file.getOriginalFilename(); String extendName = originalName.substring(originalName.lastIndexOf(".")); String newName = UUID.randomUUID().toString().concat(extendName); Client client = Client.create(); WebResource resource = client.resource(ServerUrl + newName); resource.put(String.class,file.getBytes()); map.put("message","success"); map.put("url",ServerUrl + newName); return map; } }
|
效果图
