SpringMVC实现文件上传

本文详细介绍SpringMVC中文件上传的实现方法,包括传统方式和跨服务器上传,讲解了必要的配置步骤和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringMVC实现文件上传

 

1. 文件上传的必要前提

 

A form表单的enctype取值必须是:multipart/form-data (支持二进制数据)

    (默认值是:application/x-www-form-urlencoded) (支持传递参数,例如:?    
    username=zhangsan&age=18)
    
    enctype:是表单请求正文的类型

B method属性取值必须是Post

C 提供一个文件选择域<input type=”file” />

 

 

2. 文件上传的原理分析

form表单的enctype取值不是默认值后(例如:multipart/form-data),request.getParameter()将失效。

默认值:

enctype=”application/x-www-form-urlencoded”时,form表单的正文内容是: 

key=value&key=value&key=value

form表单的enctype取值为Mutilpart/form-data时,请求正文内容就变成: 每一部分都是MIME类型描述的正文

-----------------------------7de1a433602ac 分界符 
Content-Disposition: form-data; name="userName" 协议头 
aaa 协议的正文 
-----------------------------7de1a433602ac 
Content-Disposition: form-data; name="file"; filename="C:\Users\zhy\Desktop\fileupload_demofile\b.txt" 
Content-Type: text/plain 协议的类型(MIME类型) 
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 
-----------------------------7de1a433602ac-- 

 

3. 借助第三方组件实现文件上传

使用Commons-fileupload组件实现文件上传,需要导入该组件相应的支撑jar包:Commons-fileupload和commons-io。commons-io 不属于文件上传组件的开发jar文件,但Commons-fileupload 组件从1.1 版本开始,它工作时需要commons-io包的支持。

 

4.   springmvc传统方式的文件上传

说明

传统方式的文件上传,指的是我们上传的文件和访问的应用存在于同一台服务器上。

并且上传完成之后,浏览器可能跳转。

实现步骤

第一步:创建项目,导入jar包

pom.xml

<!-- 版本锁定 -->
<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
  <spring.version>5.0.2.RELEASE</spring.version>
</properties>



<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
  </dependency>

  <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
    <scope>provided</scope>
  </dependency>

  <dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>

  <dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
  </dependency>
  <dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
  </dependency>

</dependencies>
第二步:web.xml
<!-- SpringMVC的核心控制器 -->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!-- 配置servlet启动时加载对象 -->
    <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>

第三步: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/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.itheima.controller"/>

    <!--视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <mvc:annotation-driven></mvc:annotation-driven>

    <!-- 设置静态资源不过滤 -->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>

</beans>

第四步:导入index.jsp

<body>
<a href="user/testFileUpload">文件上传</a>
</body>

第五步:导入UserController.java

@Controller
@RequestMapping(path = "/user")
public class UserController {

    // 文件上传
    @RequestMapping(path="/testFileUpload")
    public String testFileUpload(){
        System.out.println("执行了testFileUpload方法!");
        return "success";
    }

}

导入WEB-INF/pages/success.jsp

<body>
<h1>文件上传成功</h1>
</body>

 

发布到tomcat,测试。

 

 

5. 普通文件上传

index.jsp

<%--
   enctype="multipart/form-data"把请求体分成多个部分上传
--%>
<form action="user/testFileUpload1" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"><br/>
    <input type="submit" value="上传"/><br/>
</form>

UserController.java

// 文件上传
@RequestMapping(path="/testFileUpload1")
public String testFileUpload1(HttpServletRequest request) throws Exception {
    System.out.println("执行了testFileUpload1方法!");
    // 上传的位置,获取到项目根目录下的uploads文件夹绝对路径
    String path = request.getSession().getServletContext().getRealPath("/uploads");
    // 创建file对象
    File file = new File(path);
    // 判断是否存在
    if(!file.exists()) {
        // 创建目录
        file.mkdirs();
    }

    // 创建磁盘文件项工厂
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload fileUpload = new ServletFileUpload(factory);
    // 解析request
    List<FileItem> list = fileUpload.parseRequest(request);
    // 遍历,获取到每一个文件项的对象
    for (FileItem fileItem : list) {
        // 判断,当前fileItem是否是文件项
        if(fileItem.isFormField()) {
            // 说明是普通的表单 ,文本框
        }else {
            // 一定文件上传项 fileItem
            // 获取到文件的名称
            String filename = fileItem.getName();
            // 生成唯一标识
            String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
            filename = uuid+"_"+filename;
            // 上传文件
            fileItem.write(new File(file, filename));
            // 删除临时文件
            fileItem.delete();
        }
    }

    return "success";
}

 

查看上传结果:

 

 

 

6.  SpringMVC传统方式文件上传

简化ServletFileUpload的写法。

SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的name属性名称相同。

 

第一步:springmvc.xml中配置

配置文件解析器对象

<!-- 配置文件解析器对象,要求id名称必须是multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--文件大小限制:10*1024*1024字节,表示10M-->
    <property name="maxUploadSize" value="10485760"/>
</bean>

第二步:index.jsp

<hr>
<form action="user/testFileUpload2" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"><br/>
    <input type="submit" value="上传"/><br/>
</form>

第三步:UserController.java

/**
 * 使用的是SpringMVC的文件上传
 * 框架提供了一个类,表示上传文件的对象,底层已经帮你解析了request对象,把文件上传对象通过方法的参数传递进来
 *
 * MultipartFile upload    变量名称必须和表单file标签的name属性名称相同,上传文件的对象,SpringMVC框架传递给你的。
 *
 * @param request
 * @return
 * @throws Exception
 */
@RequestMapping("/testFileUpload2")
public String testFileUpload2(HttpServletRequest request,MultipartFile upload) throws Exception {
    System.out.println("SpringMVC的上传文件...");
    // 上传的位置,获取到项目根目录下的uploads文件夹绝对路径
    String path = request.getSession().getServletContext().getRealPath("/uploads");
    // 创建file对象
    File file = new File(path);
    // 判断是否存在
    if(!file.exists()) {
        // 创建目录
        file.mkdirs();
    }

    // 获取到文件的名称
    String filename = upload.getOriginalFilename();
    // 生成唯一标识
    String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
    filename = uuid+"_"+filename;
    // 使用upload对象中方法就直接上传文件
    upload.transferTo(new File(file, filename));

    return "success";
}

 

7. springmvc跨服务器方式的文件上传

1. 分服务器的目的

在实际开发中,我们会有很多处理不同功能的服务器。例如:

应用服务器:负责部署我们的应用 (源码)

数据库服务器:运行我们的数据库

缓存和消息服务器:负责处理大并发访问的缓存和消息

文件服务器:负责存储用户上传文件的服务器。

图片服务器:负责存储用户上传的图片的信息。

(注意:此处说的不是服务器集群)

分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

 

 

 

准备两个tomcat服务器,并创建一个用于存放图片的web工程

第一步:创建工程

选择项目,右键,new一个Module

第二步:创建2个tomcat服务器

一个应用服务器:用来启动springmvc_day02_fileupload(端口:8080)

另一个图片服务器:用来启动springmvc_day02_fileuploadserver(端口:9090)

两个服务器的端口需要不一致

同时在图片服务器上创建upload文件夹,用来指定上传的文件。

 

 

导入jar包

在我们负责处理文件上传的项目中拷贝文件上传的必备jar

导入开发需要的jar包

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>

<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-core</artifactId>
  <version>1.18.1</version>
</dependency>
<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-client</artifactId>
  <version>1.18.1</version>
</dependency>

 

 

文件上传

<hr>
<form action="user/testFileUpload3" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"><br/>
    <input type="submit" value="上传"/><br/>
</form>

UserController.java

/**
 * 跨服务器上传文件,把文件上传到图片服务器中去
 * @param upload
 * @return
 * @throws Exception
 */
@RequestMapping("/testFileUpload3")
public String testFileUpload3(MultipartFile upload) throws Exception {
    System.out.println("跨服务器上传文件...");

    // 指定上传文件的路径
    String path = "http://localhost:9090/springmvc_day02_fileuploadserver/uploads/";

    // 获取到文件的名称
    String filename = upload.getOriginalFilename();
    // 生成唯一标识
    String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
    filename = uuid+"_"+filename;

    // 上传文件
    // 创建客户端对象
    Client client = Client.create();
    filename = path+filename;
    // 连接图片服务器
    WebResource webResource = client.resource(filename);
    // 把文件上传到图片服务器上
    webResource.put(upload.getBytes());

    return "success";
}

查看上传的文件:

可在success.jsp中,显示上传的图片

<body>
    ${pageContext.request.contextPath}
    <h1>访问成功!</h1>
    <img src="http://localhost:8088/springmvc_day02_fileuploadserver/upload/D7E35E6EDAC94039BDE6533BEFF8F981_02.jpg"/>
</body>

注意:如果抛出异常:returned a response status of 403 Forbidden

出现这个错误的原因是因为我将图片上传单独部署了一个服务器。但是图片不能写入。需要在这个存储图片的项目所在的tomcat中配置可写操作。具体的是在Tomcat目录下的conf文件夹下的web.xml中加入

加入此行的含义是:接收文件的目标服务器可以支持写入操作。

<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>readonly</param-name>
			<param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
</servlet>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值