SpringMVC文件上传下载实战(单文件、多文件)(上)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 文件上传和下载是互联网web应用非常重要的组成部分,它是信息交互传输的重要渠道之一。你可能经常在网页上传下载文件,你可能也曾沉浸于互联网技术的神秘,而本篇就为你解开它神秘的面纱。

前言



大家好,我是bigsai,今天我们学习Springmvc的文件上传下载。


文件上传和下载是互联网web应用非常重要的组成部分,它是信息交互传输的重要渠道之一。你可能经常在网页上传下载文件,你可能也曾沉浸于互联网技术的神秘,而本篇就为你解开它神秘的面纱。


本文已收录在公众号:bigsai中(微信搜索bigsai),,同时也收录在博学谷中(以关卡方式展开欢迎体验),更多好玩精彩等待给您分享,欢迎关注!


案例分析



你肯定会问:通过本篇可能能够学到什么?


那我很负责任的告诉你,通过本篇文章,你能够掌握Springmvc文件上传(单文件、多文件)文件下载知识和内容的使用,并能够根据这些实现一些基本的案例。


核心思路拆解


你可能会问:,这么一个完整的项目是如何分工运行?


不急不急,我来告诉你,其实这么一个文件上传下载的项目,它是一个b-s结构的web项目,涉及到前端和服务端,从宏观来看它是这样的一个结构:


20200724204442361.png

但是从文件上传、下载两个功能来看它们之间又是有所区别的,文件上传的主要核心是用户上传的文件服务端接受存储


20200718143643934.png


而文件下载更重要的部分是用户请求之后服务端给用户返回二进制文件


20200724205548688.png

所以文件上传和文件下载的项目大体结构相似,只是各个部分在具体实现上有差别,我们需要更多关注下文件上传和下载服务端的实现和区别。


案例所涉及知识点


在本案例中,用到了以下知识点:


html页面form表单:


在前端无论是html还是jsp等模板引擎编写上传的页面时候。<form> 标签就意为一个(文件)上传的表单。


表单能够包含若干 input 标签,而input标签又有不同类型比如文本字段、复选框、单选框、文件等等。


我们通常使用表单编写若干标签代表我们想要向服务端发送的数据,然后通过标签的按钮将数据请求提交至服务端。


表单的method表示请求的类型(一般为post),action表示需要请求的url地址,enctype表示传输数据类型。


Springmvc:


案例的文件上传和下载基于Springmvc,而我们在Springboot项目中整合Springmvc。


本案例使用Springmvc作为项目mvc架构的框架,将模型(Model),视图(View),控制器(Controller)分离降低项目的耦合性。


本案例使用Springmvc的MultipartFile接口和ResponseEntity接口实现文件上传和下载。


创建Springmvc项目


Springmvc为一个mvc架构的web框架,创建Springmvc项目的方式有很多,你可以选择直接通过IDEA创建Springmvc项目,也可以通过Maven方式创建web项目然后添加Springmvc的依赖,但这两种方式有太多的配置还需要配置tomcat,在效果一致的情况下咱们尽量简化一些开发配置类的工作,所以不采用以上两种方式创建项目。


而Springboot简化了Spring项目的开发,开箱即用,且内嵌tomcat,所以咱们选择创建基于Springboot且整合Springmvc的项目方便快捷,更能直奔主题进行操作。


项目创建


首先,打开IDEA,创建项目,选择Spring Initializr类型初始化点击next。


20200720123900755.png


然后你会得到一个选择项目名和一些配置的页面,我们在Group中填写com,而Artifact咱们填写fileupload。点击next。


20200720124328101.png


接着在选择对应模块依赖的时候,选择Spring web 模块,此模块就是包含Springmvc的web模块


20200720124522982.png


接着选择需要创建项目的地址目录,点击next


20200720124639344.png


这样你就可以得到一个完整的包含web模块(Springmvc)的Springboot项目,就可以在里面编写咱们项目的代码。


20200720124934890.png


目录介绍


上面创建完的基于Springboot的Springmvc项目,默认有若干文件和文件夹,不同文件和文件夹有着不同的职责:


  • java:用来编写java服务端相关代码,例如Controller,Dao,Service等。
  • application.properties: 编写一些项目和框架的配置内容以及和第三方框架整合配置等
  • static: 静态资源目录,用来存放html、JavaScript、图片等资源。
  • teamplates:用来编写Thymeleaf等模板引擎,这里不使用
  • pom.xml:编写maven项目jar包资源依赖。如果项目需要引入其他依赖或者修改打包方式可以进行修改。


对于web项目的文件上传,需要进行一定配置以满足我们的使用需求,我们在application.propertis进行以下配置:


# 允许项目中文件上传
spring.servlet.multipart.enabled=true
# 上传文件的临时目录 (一般情况下不用特意修改)
#spring.servlet.multipart.location=
# 上传文件最大为 1M (默认值 1M 根据自身业务自行控制即可)
spring.servlet.multipart.max-file-size=104857600
# 上传请求最大为 10M(默认值10M 根据自身业务自行控制即可)
spring.servlet.multipart.max-request-size=104857600
# 文件大小阈值,当大于这个阈值时将写入到磁盘,否则存在内存中,(默认值0 一般情况下不用特意修改)
spring.servlet.multipart.file-size-threshold=0
# 判断是否要延迟解析文件(相当于懒加载,一般情况下不用特意修改)
spring.servlet.multipart.resolve-lazily=false


当然,你对文件有大小等其他要求可以对配置进行自行更改。到这里带有Springmvc环境的项目已经创建完成啦,剩下的只需要编写前端、服务端代码运行测试即可。


单文件上传



下面请跟我实战 Springmvc单文件上传。一个完整的文件上传项目有两部分组成:前端界面和服务端程序。


前端设计


对于前端页面,我们使用你一定熟悉的html而不选用其他模板引擎。而form表单是html文件上传的核心组件,你在使用前需要了解它的一些属性。


表单的enctype属性


上面说了一个表单文件传输的大体流程,你也知道表单有个至关重要的属性:enctype。而entype值通常有以下三种:


application/x-www-form-urlencoded:默认编码方式,在发送前编码所有字符(默认)使用url编码方式,和get请求有些相似。但这种方式如果发送大量二进制数据效率会比较低。


multipart/form-data:不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。通常用来向服务端发送二进制数据,而我们的文件也主要以二进制的方式进行传输。


text/plain:空格转换为 “+” 加号,但不对特殊字符编码。


所以本单文件上传案例中,需要注意以下事项:


表单的enctype要为multipart/form-data类型,表示二进制传输。


在一个form表单内定义一个input为file属性的标签,代表文件上传。


form表单的method需要为post。


enctype要为multipart/form-data类型,表示二进制传输。


前端页面的规则了解之后你在static下创建一个index1.html文件,里面具体的代码内容为:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单文件上传</title>
</head>
<body>
<h2>单文件上传</h2>
<form  action="onfile" method="post" enctype='multipart/form-data'>
    <input type="file" name="file" ><br>
    <input type="submit" value="提交">
</form>
</body>
</html>


其中action="onfile"代表的为请求地址为onfile,这里都在项目内所以用相对地址即可,如果上传为其他接口也可填写对应的绝对地址。这样前端页面就编写完成,我们还需要编写文件上传对应服务端模块。


服务端设计


服务端主要负责文件接受,在前端看起来实现文件上传的页面很简单,但实际上在服务端的文件接收并没有那么容易,因为传过来的不光光是这一个(或多个)二进制文件,还附带一些头信息、文件名等等数据。打包过来的数据如果是文本数据解析可能还好,但是二进制文件数据一旦出现一点错误可能得到的整个文件都是损坏的。并且在咱们java web技术栈中文件上传也是有一定发展的历史的:


servlet文件上传(3.0以前)


在servlet3.0以前,文件上传在服务端接收需要使用request.getInputStream()获取表单的二进制数据,但是在解析时候非常麻烦和复杂,对于文件上传这么一个很基本的模块在接收的时候可能要耗费很大的成本和精力去解决它,并且很多初级攻城狮很可能由于对io模块陌生无法实现上传文件在服务端的接收。


20200718205826741.gif


所以这个时候一些具有责任感的公司、组织就把它们的解析方法贡献出来供大家使用,大家不需了解传输文件底层内容,这些开源的处理方式中,最流行的当属apache旗下开源的commons-fileupload和 commons-io,把两个jar包加入到项目中你直接了解下这个api如何使用即可。有了这两个jar包,简单学习它的api,你就可以在普通的web项目中很容易的实现上传文件的功能!


20200718212517943.png


servlet3.0以后


随着servlet版本更新,设计者可能看到javaweb开发中原生api对文件上传支持不太友好的问题,所以在api对文件上传的支持得到优化,简化了Java Web的开发。在servlet3.0中主要增加Part这个类用来读取文件数据和信息,在Part中直接将传输文件的名称、头信息、二进制文件分割开,通过简单的api就可以实现文件上传的功能。不需要再添加外部jar包。


Springmvc文件上传


文件上传和下载是web开发常用模块,而Springmvc作为一款优秀的web框架,对很多模块和内容进行更高度的封装和集成,而这么常用的文件上传肯定是少不了的,所以Springmvc的文件上传基于apache旗下开源的commons-fileupload和 commons-io包。将其进行二次集成和封装至Springmvc,将方法和内容封装至MultipartFile接口让我们使用起来更加方便,能够容易实现单文件、多文件上传。


对于上述各种文件上传服务端实现方式,大致可以通过下图展示:


20200719143418191.png


通过上图你就可明白Springmvc文件上传实现的原理,那么下面你就可以进行大显身手啦!Springmvc处理上传文件很简单,我们需要在java目录下创建一个uploadController.java创建这么一个控制器,在上面加上@Controller注解。在

Controller中编写以下代码:


 @PostMapping("onfile")
 @ResponseBody
 public String onfile(MultipartFile file) throws IOException {
     File file1 =new File("F:/fileupload/"+file.getOriginalFilename());//创建file对象
     if(!file1.exists())
            file1.createNewFile();//在磁盘创建该文件
     file.transferTo(file1);//将接受的文件存储
     return "sucucess";
 }


其中:


@PostMapping(“onfile”) 的意思为该请求方式为post,且请求的url在项目中的相对地址为onfile


@ResponseBody指不返回web页面,而是返回字符串或json字符串,在这里我们直接用一个成功单词代表跳转后的界面。


public String onfile(MultipartFile file) 函数名不重复就行,而MultipartFile file就是Springmvc封装的一个处理文件的接口,其中参数名(这里是file)要和前端界面文件名相同(input type=“file”,name="file"中的name),通过这个接口你可以更容易的对文件进行各种操作,而本案例就是将上传的文件保存到本地F盘。


对于函数中的几行核心代码各司其职,除了注释的解释外,大致的流程可以参考如下图:


20200720220027233.png


运行测试


这样启动项目,在浏览器输入http://localhost:8080/index1.html,选择文件上传,点击上传之后就可以在本地看到上传的文件啦。


20200721150008304.png


至此,单文件上传就完成啦,单文件上传前端需要注意的就是form表单的method类型以及 enctype参数,而服务端也只需要用MultipartFile 接口就可以很容易的对文件进行接受。


目录
相关文章
|
4月前
|
XML 前端开发 Java
SpringMVC入门到实战------2、SpringMVC创建实例Hello SpringMVC(maven+tomcat)
这篇文章是SpringMVC框架的入门教程,详细指导了如何在IDEA中使用Maven和Tomcat创建SpringMVC工程,包括添加依赖、配置web.xml、编写控制器、创建配置文件、配置Tomcat服务器以及进行基本的测试,展示了一个简单的Hello SpringMVC示例。
SpringMVC入门到实战------2、SpringMVC创建实例Hello SpringMVC(maven+tomcat)
|
7月前
SpringMVC之文件上传和下载
【1月更文挑战第20天】SpringMVC之文件上传和下载
45 1
SpringMVC入门到实战------5、域对象共享数据 Request、Session、Application、Model、ModelAndView、Map、ModelMap的详细使用及代码实例
这篇文章详细解释了在IntelliJ IDEA中如何使用Mute Breakpoints功能来快速跳过程序中的后续断点,并展示了如何一键清空所有设置的断点。
SpringMVC入门到实战------5、域对象共享数据 Request、Session、Application、Model、ModelAndView、Map、ModelMap的详细使用及代码实例
|
4月前
|
存储 前端开发 Java
SpringMVC入门到实战------1、SpringMVC简介
这篇文章是SpringMVC框架的入门介绍,阐述了MVC架构的概念和分层,解释了SpringMVC作为Spring家族的一部分在Web应用开发中的作用和重要性,并概述了SpringMVC的关键特点,包括与Spring IOC容器的无缝集成、基于Servlet的DispatcherServlet、全面的解决方案、代码简洁性、高内聚低耦合的组件化设计以及卓越的性能表现。
SpringMVC入门到实战------ 十一 拦截器的使用
这篇文章介绍了SpringMVC中拦截器的使用,包括拦截器的配置、拦截器的三个抽象方法`preHandle`、`postHandle`和`afterCompletion`的作用,以及多个拦截器的执行顺序和规则。
SpringMVC入门到实战------ 十一 拦截器的使用
|
4月前
|
JSON 前端开发 JavaScript
SpringMVC入门到实战------九 HttpMessageConverter @RequestBody 、@ResponseBody 、RequestEntity、ResponseEntity
这篇文章详细介绍了SpringMVC中的`HttpMessageConverter`接口及其相关的`@RequestBody`、`@ResponseBody`、`RequestEntity`和`ResponseEntity`注解和类型的使用,包括如何将请求体转换为Java对象、如何将Java对象转换为响应体、以及如何处理JSON和AJAX请求。
SpringMVC入门到实战------九 HttpMessageConverter @RequestBody 、@ResponseBody 、RequestEntity、ResponseEntity
|
4月前
|
缓存 Java 应用服务中间件
SpringMVC入门到实战------七、SpringMVC创建JSP页面的详细过程+配置模板+实现页面跳转+配置Tomcat。JSP和HTML配置模板的差异对比(二)
这篇文章详细介绍了在SpringMVC中创建JSP页面的全过程,包括项目的创建、配置、Tomcat的设置,以及如何实现页面跳转和配置模板解析器,最后还对比了JSP和HTML模板解析的差异。
SpringMVC入门到实战------七、SpringMVC创建JSP页面的详细过程+配置模板+实现页面跳转+配置Tomcat。JSP和HTML配置模板的差异对比(二)
|
4月前
|
XML JSON 数据库
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
这篇文章详细介绍了RESTful的概念、实现方式,以及如何在SpringMVC中使用HiddenHttpMethodFilter来处理PUT和DELETE请求,并通过具体代码案例分析了RESTful的使用。
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
|
4月前
|
前端开发
SpringMVC入门到实战------六、SpringMVC的视图。ThymeleafView、转发视图、重定向视图、视图控制器的使用详解
这篇文章详细介绍了SpringMVC中的视图类型,包括ThymeleafView、转发视图、重定向视图和视图控制器的使用,以及如何通过源码查看确定使用的视图渲染器类型。
SpringMVC入门到实战------六、SpringMVC的视图。ThymeleafView、转发视图、重定向视图、视图控制器的使用详解
SpringMVC入门到实战------十二、异常处理器
这篇文章介绍了SpringMVC中拦截器的使用,包括拦截器的配置、拦截器的三个抽象方法`preHandle`、`postHandle`和`afterCompletion`的作用,以及多个拦截器的执行顺序和规则。