Spring Web MVC框架(五) 文件上传

简介: Spring同样支持文件上传功能,不过该功能默认未开启,因为可能有些开发者可能希望自己处理文件上传过程。Spring的文件上传功能在org.springframework.web.multipart包下,有两个MultipartResolver实现用来支持文件上传功能,一个是基于Commons FileUpload ,另一个基于Servlet 3.0 multipart请求解析功能。

Spring同样支持文件上传功能,不过该功能默认未开启,因为可能有些开发者可能希望自己处理文件上传过程。Spring的文件上传功能在org.springframework.web.multipart包下,有两个MultipartResolver实现用来支持文件上传功能,一个是基于Commons FileUpload ,另一个基于Servlet 3.0 multipart请求解析功能。这两个MultipartResolver差不多,一个需要添加Commons FileUpload的依赖,另一个需要在Servlet 3.0容器上运行。大家可以根据需要选择。

定义MultipartResolver

使用Commons FileUpload MultipartResolver

在配置文件中添加如下一段,我们可以在Bean定义中配置上传文件大小等属性。

<bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

    <!-- one of the properties available; the maximum file size in bytes -->
    <property name="maxUploadSize" value="100000"/>

</bean>

使用Servlet 3.0 MultipartResolver

由于使用的是Servlet API提供的文件上传功能,所以文件大小等配置需要在web.xml中进行配置。我们需要在dispathcer-servlet中添加<multipart-config>标签,它有四个子标签来设置文件上传的属性。

这四个属性如下:

  • location ,临时文件的存放位置,这个路径必须是绝对路径。
  • fileSizeThreshold,文件起始值,大于该值文件才会被临时保存,单位是字节。
  • MaxFileSize,单个文件的最大值,单位是字节,不管上传几个文件,只要有一个文件大小超过该值就会抛出IllegalStateException
  • maxRequestSize,文件上传请求的最大值,单位是字节,主要作用是当上传多个文件是配置整个请求的大小,当超出该值是抛出IllegalStateException
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
    <multipart-config>
        <max-file-size>100000</max-file-size>
    </multipart-config>
</servlet>

然后我们在Spring配置文件中添加Servlet 3.0 MultipartResolver。

<bean id="multipartResolver"
        class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>

获取文件

配置好了Multipart解析器之后,我们就可以接收文件了。首先定义一个页面fileupload.jsp,用于上传文件并显示服务器中的文件。注意在表单中我们必须添加enctype="multipart/form-data"才能正确的上传文件。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
    <meta charset="utf-8">

</head>
<body>
<h2>文件上传</h2>
<form action="<c:url value="/fileupload"/>"
      method="post" enctype="multipart/form-data">
    <label for="file">文件</label>
    <input type="file" name="file" id="file"/>
    <br>
    <input type="submit" value="提交">
</form>

<h2>文件下载</h2>

<c:forEach var="file" items="${files}">
    <a href="<c:url value="/findFile?filename=${file}"/>">${file}</a>
    <br>
</c:forEach>

</body>
</html>

然后就可以在控制器中获取文件了。由于MultipartFile和它对应的临时文件会在方法结束之后被Spring清除,所以我们必须在方法中将文件保存到合适的地方。这里我定义了一个UserFile类将文件保存到Session中。

public class UserFile {
    private String filename;
    private byte[] bytes;
}

然后就是控制器了。在请求方法中,我们可以像普通参数那样获取上传的文件,只不过文件对应的类型是MultipartFile,如果使用的是Servlet 3.0标准的,那么类型还可以是javax.servlet.http.Part。我写了两个处理方法,第一个将MultipartFile转化为上面的类型,然后保存到Session中。第二个方法用于获取Session中的文件。

@Controller
public class FileUploadController {
    @RequestMapping("/fileupload")
    public String fileUpload(HttpSession session, @RequestParam(required = false) MultipartFile file, Model model) throws IOException {
        List<UserFile> files = (List<UserFile>) session.getAttribute("files");
        if (files == null)
            files = new ArrayList<>();
        if (file != null) {
            UserFile f = new UserFile();
            f.setFilename(file.getOriginalFilename());
            f.setBytes(file.getBytes());
            files.add(f);
        }
        session.setAttribute("files", files);
        List<String> filenames = files.stream()
                .map(UserFile::getFilename)
                .collect(Collectors.toList());
        model.addAttribute("files", filenames);

        return "fileupload";
    }

    @RequestMapping("/findFile")
    public void findFile(HttpSession session, @RequestParam String filename, HttpServletResponse response) throws IOException {
        List<UserFile> files = (List<UserFile>) session.getAttribute("files");
        Optional<UserFile> file = files.stream()
                .filter(o -> Objects.equals(o.getFilename(), filename))
                .findFirst();
        OutputStream out = response.getOutputStream();
        out.write(file.get().getBytes());
    }
}
相关文章
|
8月前
|
缓存 安全 Java
《深入理解Spring》过滤器(Filter)——Web请求的第一道防线
Servlet过滤器是Java Web核心组件,可在请求进入容器时进行预处理与响应后处理,适用于日志、认证、安全、跨域等全局性功能,具有比Spring拦截器更早的执行时机和更广的覆盖范围。
|
8月前
|
开发框架 前端开发 Go
【GoGin】(0)基于Go的WEB开发框架,GO Gin是什么?怎么启动?本文给你答案
Gin:Go语言编写的Web框架,以更好的性能实现类似Martini框架的APInet/http、Beego:开源的高性能Go语言Web框架、Iris:最快的Go语言Web框架,完备的MVC支持。
674 1
|
9月前
|
存储 安全 Java
如何在 Spring Web 应用程序中使用 @SessionScope 和 @RequestScope
Spring框架中的`@SessionScope`和`@RequestScope`注解用于管理Web应用中的状态。`@SessionScope`绑定HTTP会话生命周期,适用于用户特定数据,如购物车;`@RequestScope`限定于单个请求,适合无状态、线程安全的操作,如日志记录。合理选择作用域能提升应用性能与可维护性。
390 1
|
开发框架 JSON 中间件
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。
|
10月前
|
存储 NoSQL Java
探索Spring Boot的函数式Web应用开发
通过这种方式,开发者能以声明式和函数式的编程习惯,构建高效、易测试、并发友好的Web应用,同时也能以较小的学习曲线迅速上手,因为这些概念与Spring Framework其他部分保持一致性。在设计和编码过程中,保持代码的简洁性和高内聚性,有助于维持项目的可管理性,也便于其他开发者阅读和理解。
274 0
|
开发框架 安全 前端开发
Go Web开发框架实践:模板渲染与静态资源服务
Gin 是一个功能强大的 Go Web 框架,不仅适用于构建 API 服务,还支持 HTML 模板渲染和静态资源托管。它可以帮助开发者快速搭建中小型网站,并提供灵活的模板语法、自定义函数、静态文件映射等功能,同时兼容 Go 的 html/template 引擎,具备高效且安全的页面渲染能力。
|
人工智能 自然语言处理 JavaScript
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
Magnitude是一个基于视觉AI代理的开源端到端测试框架,通过自然语言构建测试用例,结合推理代理和视觉代理实现智能化的Web应用测试,支持本地运行和CI/CD集成。
2463 15
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
|
开发框架 JSON 中间件
Go语言Web开发框架实践:使用 Gin 快速构建 Web 服务
Gin 是一个高效、轻量级的 Go 语言 Web 框架,支持中间件机制,非常适合开发 RESTful API。本文从安装到进阶技巧全面解析 Gin 的使用:快速入门示例(Hello Gin)、定义 RESTful 用户服务(增删改查接口实现),以及推荐实践如参数校验、中间件和路由分组等。通过对比标准库 `net/http`,Gin 提供更简洁灵活的开发体验。此外,还推荐了 GORM、Viper、Zap 等配合使用的工具库,助力高效开发。
|
11月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
794 0
|
网络协议 Java Shell
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
1106 7

热门文章

最新文章