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

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

多文件上传



上面讲的是单文件上传,很多时候你可能遇到的需求不光光是单文件上传。就比如你一定熟悉这个页面:


20200725013159194.png


如上你可以看到,这么一次文件上传不止一个图片,并且数量也不确定,但都属于同一名称和集合的内容。这就是多文件上传。对于这种情况无论在前端还是服务端也是很容易处理的。


前端设计


我们这里实现一个多张图片的上传,首先在static目录下创建一个index2.html的页面。里面的具体内容为:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>多文件上传</title>
</head>
<body>
<h2>同一类别多个文件上传</h2>
<form name="onfile"  action="onfiles2" method="post" enctype="multipart/form-data">
    图片:
    <input type="file" name="img"><br>
    <input type="file" name="img"><br>
    <input type="file" name="img"><br>
    <input type="file" name="img"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>


这样前端页面就编写完成,其中action要改为onfiles2,也就是待会要在服务端编写的接口。还有注意的这些input 所有type为file代指类型为文件,而name均为img意思是上传一组名称为img图片的集合。


服务端设计


而在我们服务端,其实用MultipartFile[]数组就可以对这样的多文件进行接收,我们在controller中编写以下代码:


@PostMapping("onfiles2")
@ResponseBody
public String onfiles2(MultipartFile img[]) throws IOException {
   for(int i=0;i<img.length;i++)
   {
       if(!img[i].isEmpty())//文件不空
       {
           File imgfile =new File("F:/fileupload/"+img[i].getOriginalFilename());
           imgfile.createNewFile();
           img[i].transferTo(imgfile);
           logger.info(img[i].getOriginalFilename());
       }
   }
    return "sucucess";
}


这个处理方式和前面的很相似,只不过是需要遍历MultipartFile[]对每个文件进行接收处理,当然文件为空的时候不进行处理。


运行测试


这样打开浏览器输入:http://localhost:8080/index2.html,上传文件测试效果:


20200725121854674.png


这样一组类似相册上传的功能就完成啦,当然实际开发中的文件上传的要求肯定比这个要求严格很多,可能对文件的格式、大小都有一定的要求,这就要求你在前端和服务端都要对文件的后缀名、大小等信息进行校验,以达到自己场景化的需求。


文件下载



文件下载估计你在日常生活中会经常遇到,而你下载的其实就是服务端(服务器)的资源,对于文件类型有多种多样的,浏览器也能够识别很多种资源,事实上你现在访问的这个网页也是服务端的html文件、图片文件等资源,只不过这些资源浏览器能够显示而不会保存到本地。


直接访问资源VS下载资源


如果直接访问的资源是浏览器所不能识别解析的,例如doc、zip等类型文件,那访问的时候会默认下载到本地。而当你在Springmvc中使用下载功能时,无论是什么资源都以下载的形式返回给客户端。这种区别可以参考下图:


20200724014234963.png


在文件下载方面的实现,servlet本身也是实现文件下载的,不过使用起来有点繁琐。其原理就是往HttpServletResponse response的输出流写字节内容。而我们Springmvc对文件下载也做了封装,将下载功能封装至ResponseEntity类中,我们在使用的时候也很方便。下面就来实战文件下载的功能。


首先,我们在F盘建立download文件夹,在里面添加对应文件,这个文件夹我们作为服务端的资源。


20200723163839232.png


前端设计


我们在创建一个文件下载的前端页面,在static目录下创建index3.html,页面的具体内容为:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Springmvc文件下载</title>
</head>
<body>
<h2>Springmvc文件下载</h2>
个人照片<a href="/download/个人照片.png">个人照片.png</a><br>
个人简历<a href="/download/个人简历.pdf">个人简历.pdf</a>
</body>
</html>


其中href是下载的超链接,download是下载的接口名,而链接最后面部分则是下载资源名称。


服务端设计


文件下载的原理就是服务端向客户端返回二进制流和信息,而Springmvc通过ResponseEntity完成。我们在controller中编写以下接口实现下载的功能:


@GetMapping("download/{filename}")
public ResponseEntity<byte[]>download(@PathVariable String filename) throws IOException {
    //下载文件的路径(这里绝对路径)
    String filepath= "F:/download/"+filename;
    File file =new File(filepath);
    //创建字节输入流,这里不实用Buffer类
    InputStream in = new FileInputStream(file);
    //available:获取输入流所读取的文件的最大字节数
    byte[] body = new byte[in.available()];
    //把字节读取到数组中
    in.read(body);
    //设置请求头
    MultiValueMap<String, String> headers = new HttpHeaders();
    headers.add("Content-Disposition", "attchement;filename=" + file.getName());
    //设置响应状态
    HttpStatus statusCode = HttpStatus.OK;
    in.close();
    ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(body, headers, statusCode);
    return entity;//返回
}



这样就是实现了文件下载功能,如果用传统servlet的方式下载文件可能需要在HttpServletResponse response中设置各种信息,而使用Springmvc的ResponseEntity只需要将文件二进制主体、头信息以及状态码设置好即可进行文件下载,在易用性和简洁上更胜一筹。


运行测试


打开浏览器输入:http://localhost:8080/index3.html;点击需要下载的文件,就实现了文件下载的功能,运行情况图如下:


20200725123215866.png

此时你就遇到了一个文件下载非常常见的问题:中文文件名错误显示。这个解决方案也很容易解决,只需将Content-Disposition内容后面的文件名进行url编码即可,具体代码为(替换上面对于部分):


headers.add("Content-Disposition", "attchement;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));


这样重启程序,刷新页面再次点击下载的链接,你就会发现文件被成功的下载了:


20200725123831159.png


总结与拓展


至此,Springmvc的单文件上传、多文件上传以及文件下载你已经全部掌握了,是不是满满的成就感想去实现一个自己的小网站并把相关内容放进去?不过Springmvc文件上传下载虽然简单,但你依然需要掌握其原理,学好java中的io文件传输,这样在各种场景的文件传输任务中方能胜任。


总结


前面所讲文件上传,前端就是form表单用<input type="file">表示客户端要上传文件,而服务端主要使用MultipartFile或者MultipartFile[]分别接收单个文件和多个文件。而在存储到本地也仅仅需要在本地磁盘创建对应文件然后MultipartFile调用transferTo()方法即可将上传的文件储存。


而文件下载的前端需要一个请求的url链接,服务端需要编写这个链接对应的接口。通过一些名称找到文件在本地真实的位置通过ResponseEntity即可将二进制文件返回给客户达到文件下载的功能。而ResponseEntity使用也很简单在创建时候只需要传入二进制主体、头和状态码即可成功返回,而这些Springmvc已进行了很好封装你可以直接使用。


而无论是文件上传、多文件上传还是文件下载,一个完整的案例大致都需要这样一个过程:


构思需求和页面大体样式

编写前端html页面

编写服务端响应的请求

启动程序运行测试

在其中过程如果有问题可以根据编译器的错误提示、运行时的错误日志找到根源进行修正,这样完整的案例就可以成功完成啦!


案例拓展


你是否觉得自己掌握的可以了?那好,咱们拓展提升一下,我给你来一个需求:单文件和多文件混合上传


假设小明需要实现一个文件上传功能,小明需要上传一份简历和若干份照片(小于3)。这个项目该如何设计呢?它的计划页面可能是这样的:


20200725152236779.png


我觉得聪明的你一定不会被难住,对于前端界面的html有什么想法呢?

对于种类来说有简历和照片两种文件,对于它们各自来说,简历只有一份,而照片可能有多份。


那么咱们的html页面可以这样设计:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>个人信息上传</title>
</head>
<body>
<h2>个人信息上传</h2>
<form name="onfile"  action="infoupload" method="post" enctype="multipart/form-data">
    姓名:<input type="text" name="name" ><br>
    年龄:<input type="text" name="age"> <br>
    图片:<input type="file" name="img">
         <input type="file" name="img">
    简历:<input type="file" name="resume"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>


这里面和前面的单文件上传不同的是有多个input标签,此外action也要改成infoupload意思是你需要写这么一个接口来处理这个文件上传的内容。在controller中编写以下代码:


 private  static Logger logger= LoggerFactory.getLogger(uploadController.class);
    @PostMapping("infoupload")
    @ResponseBody
    public String onfile(String name,String age, MultipartFile img[],MultipartFile resume) throws IOException {
        logger.info(name);//日志中打印传输的name
        logger.info(age);
        //接收img[]
        for(int i=0;i<img.length;i++)
        {
            if(!img[i].isEmpty())//文件不空
            {
                File imgfile =new File("F:/fileupload/"+img[i].getOriginalFilename());
                imgfile.createNewFile();
                img[i].transferTo(imgfile);
            }
        }
         //接收resume
        File resumefile =new File("F:/fileupload/"+resume.getOriginalFilename());
        //在磁盘中创建文件,此时文件存在但没有内容
        resumefile.createNewFile();
        //将接受的文件复制到创建的文件中
        resume.transferTo(resumefile);
        return "sucucess";
    }


这个理解起来其实也很容易,这个和上面主要的区别就是函数中的多参数,其实每一个参数都是要和前端页面的form表单input标签的内容对应(名称一致)。form表单中的file类型在Springmvc的controller中就是对应MultipartFile类型,form表单中的text类型对应controller中的String类型。如果上传单个文件,在服务端就用MultipartFile类型参数接收,如果多文件就用MultipartFile[]进行接收。上传类型和个数根据你自己的需求设计定义。


我们启动程序打开浏览器输入http://localhost:8080/index4.html选择文件进行上传,然后在本地你可以看到文件成功被保存。


20200725193840151.png


至此,本篇的内容就结束了,本文主要简单讲解了Springmvc中文件上传、多文件上传、文件下载的实现,现在你已熟练掌握。青山不改,绿水长流,我们下期再见!下课!

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