前言
大家好,我是bigsai,今天我们学习Springmvc的文件上传下载。
文件上传和下载是互联网web应用非常重要的组成部分,它是信息交互传输的重要渠道之一。你可能经常在网页上传下载文件,你可能也曾沉浸于互联网技术的神秘,而本篇就为你解开它神秘的面纱。
本文已收录在公众号:bigsai中(微信搜索bigsai),,同时也收录在博学谷中(以关卡方式展开欢迎体验),更多好玩精彩等待给您分享,欢迎关注!
案例分析
你肯定会问:通过本篇可能能够学到什么?
那我很负责任的告诉你,通过本篇文章,你能够掌握Springmvc文件上传(单文件、多文件)文件下载知识和内容的使用,并能够根据这些实现一些基本的案例。
核心思路拆解
你可能会问:,这么一个完整的项目是如何分工运行?
不急不急,我来告诉你,其实这么一个文件上传下载的项目,它是一个b-s结构的web项目,涉及到前端和服务端,从宏观来看它是这样的一个结构:
但是从文件上传、下载两个功能来看它们之间又是有所区别的,文件上传的主要核心是用户上传的文件服务端接受存储:
而文件下载更重要的部分是用户请求之后服务端给用户返回二进制文件:
所以文件上传和文件下载的项目大体结构相似,只是各个部分在具体实现上有差别,我们需要更多关注下文件上传和下载服务端的实现和区别。
案例所涉及知识点
在本案例中,用到了以下知识点:
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。
然后你会得到一个选择项目名和一些配置的页面,我们在Group中填写com,而Artifact咱们填写fileupload。点击next。
接着在选择对应模块依赖的时候,选择Spring web 模块,此模块就是包含Springmvc的web模块
接着选择需要创建项目的地址目录,点击next
这样你就可以得到一个完整的包含web模块(Springmvc)的Springboot项目,就可以在里面编写咱们项目的代码。
目录介绍
上面创建完的基于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模块陌生无法实现上传文件在服务端的接收。
所以这个时候一些具有责任感的公司、组织就把它们的解析方法贡献出来供大家使用,大家不需了解传输文件底层内容,这些开源的处理方式中,最流行的当属apache旗下开源的commons-fileupload和 commons-io,把两个jar包加入到项目中你直接了解下这个api如何使用即可。有了这两个jar包,简单学习它的api,你就可以在普通的web项目中很容易的实现上传文件的功能!
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接口让我们使用起来更加方便,能够容易实现单文件、多文件上传。
对于上述各种文件上传服务端实现方式,大致可以通过下图展示:
通过上图你就可明白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盘。
对于函数中的几行核心代码各司其职,除了注释的解释外,大致的流程可以参考如下图:
运行测试
这样启动项目,在浏览器输入http://localhost:8080/index1.html
,选择文件上传,点击上传之后就可以在本地看到上传的文件啦。
至此,单文件上传就完成啦,单文件上传前端需要注意的就是form表单的method类型以及 enctype参数,而服务端也只需要用MultipartFile 接口就可以很容易的对文件进行接受。