当前位置: 首页 > news >正文

SpringMVC | SpringMVC中的 “文件上传和下载”

目录:

    • 一、文件上传
      • 1.1 文件上传“概述”
      • 1.2 文件上传“具体配置” :
        • “前端”中配置“文件上传” ( type=“file” + 满足3个条件 )
        • “后端”中配置“文件上传” ( 配置id为“CommonsMultipartResolver”的bean + 配置“文件上传”的“约束条件” + 通过“MultipartFile接口”参数接收“传来的文件”)
      • 1.3 文件上传“应用案例” :
        • 文件上传 (存储在“相对路径”)
        • 文件上传 (存储在“绝对路径”)
    • 二、文件下载
      • 2.1 实现“文件下载” ( “不可”下载“非中文名称”文件 )
      • 2.2 “中文名称”的文件下载 ( “可”下载“中文名称”文件 )

在这里插入图片描述

作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!

该文章参考学习教材为:
《Java EE企业级应用开发教程 (Spring + Spring MVC +MyBatis)》 黑马程序员 / 编著
文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章

文章用于本人学习使用 , 同时希望能帮助大家。
欢迎大家点赞👍 收藏⭐ 关注💖哦!!!

(侵权可联系我,进行删除,如果雷同,纯属巧合)


一、文件上传

1.1 文件上传“概述”

  • 上文件上传下载项目 开发中 最常用功能,例如图片的上传与下载邮件附件上传下载等。

1.2 文件上传“具体配置” :

“前端”中配置“文件上传” ( type=“file” + 满足3个条件 )
  • 多数文件上传 都是通过 表单形式 提交给 后台服务器 的,因此,要实现文件上传功能,就需要提供一个 文件上传表单,而 该表单 必须 满足以下3个条件 :

    form表单method属性设置为post
    form表单enctype属性 (编码方式) 设置为 multipart/form-data (多部分/表单数据)
    提供 <input type=”file” name=filename" multiple=“multiple”/>文件上传输入框

    ps
    multiple=“multiple”可选属性,表示 可以 一次性选择多个文件来上传

  • 文件上传 表单的 示范代码 如下 : (“前端”中配置“文件上传”)

    <%-- 通过表单的方式进行文件上传--%>
    <form action="/uploadUrl" method="post" enctype="multipart/form-data">
    <%--  multiple="multiple 为可选属性,表示一次可以选择多个文件上传  --%><input type="file" name="filename" multiple="multiple">
    </form>
    

    上述代码中,除了满足上传表单必须的3个条件外,在 <input>元素中还增加了一个 multiple属性,该属性HTML5新属性,如果使用了该属性,则可以同时选择多个文件进行上传,即 多文件上传

    客户端form表单enctype属性 (multipart/form-data)为 multipart/form-data 时,浏览器 就会采用 二进制流 的方式来 处理表单数据服务器端 就会对 文件上传请求进行解析处理

“后端”中配置“文件上传” ( 配置id为“CommonsMultipartResolver”的bean + 配置“文件上传”的“约束条件” + 通过“MultipartFile接口”参数接收“传来的文件”)
  • Spring MVC中为文件上传提供了直接的支持,这种支持是通过 MultipartResolver (多部件解析器) 对象实现的。MultipartResolver ( 多部件解析器 )是一个接口对象,需要通过它的 实现类 : CommonsMultipartResolver 来完成 文件上传工作。在Spring MVC中使用 MultipartResolver对象非常简单只需要配置文件中定义MultipartResolver接口Bean 即可。

    (配置 idCommonsMultipartResolverbean )

  • 除了配置 CommonsMultipartResolver类之外,还可以通过 <property>元素配置文件上传”的“约束条件 ,具体 文件上传”的“约束条件 如下 :

约束条件描述
<property name=“defaultEncoding” value=“xxx”/>配置 请求编码格式必须JSP中的 pageEncoding属性一致默认ISO-8859-1
<property name=“maxUploadSize” value=“xxx”/>设置 上传文件最大长度单位字节
<property name="maxInMemorySize" value=“xxx”/>设置 缓存中最大尺寸
ps :
maxInMemorySize最大内存大小
<property name=“resolveLazily” value=“xxx”/>推迟文件解析以便Controller捕获文件大小异常

例子如 : ( springmvc-config.xml配置 “文件上传” )

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--  配置Springmvc的“文件上传”  -->
<!--   配置id为CommonsMultipartResolver的bean -->
<!--
因为实现类CommonsMultipartResolver的内部是引用multipartResolver的知识点来获取“该实现类对象”并完成“文件解析”的,所以该bean的id名必须为: multipartResolver
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 配置“请求编码格式”,必须与JSP中的pageEncoding的属性一致,默认是ISO-8859-1 -->
<property name="defaultEncoding" value="UTF-8"/>
<!-- 设置上传文件的最大长度,单位为字节  -->
<!-- 1MB = 1024KB ,1KB = 1024B ,2MB = 2X1024X1024 = 2097152B(字节)-->
<property name="maxUploadSize" value="2097152"/>
</bean></beans>

上述配置代码中,配置了 CommonsMultipartResolver类 外,还通过 <property>元素配置了 编码格式允许上传文件的大小

注意 :

因为MuliparResolver接口实现类CommonsMulipartResolver内部是引用muliparReolver字符
获取该实现类对象完成文件解析
,所以在配置CommonsMulipartResolver必须指定该BeanidmulipartResolver

  • 由于 CommonsMultipartResolverSpringMVC内部通过 Apache Commons FileUpload 技术实现的,所以 SpringMVC文件上传需要依赖Apache Commons FileUpload的组件,即需要导入支持文件上传相关JAR包具体如下 :

    commons-fileupload-1.3.2.jar
    commons-io-2.5.jar
    SpringMVC所需JAR
    SpringMVC中“文件上传”和“下载”所需JAR

  • 后端处理器方法 中是通过 MultipartFile接口类型参数接收前端传来文件 的,例子如下

    package com.myh.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.multipart.MultipartFile;@Controller //将该被设置为"处理器"类
    public class FileUploadController { //文件上传的“控制器类”@RequestMapping("/fileUpload")//使用@RequestParam("前端参数名")注解注解“前后端参数名不一致的问题”,让数据之间能够完成映射/赋值//通过"MultipartFile接口"来接受前端传来的文件public String handlerFormUpload(@RequestParam("filename") MultipartFile file) { //MultipartFile 是一个接口if (!file.isEmpty()) { //如果文件不为空//具体的执行方法...return "uploadSuccess";}return "uploadFailure";}
    }
    

    上述代码中,包含一个 MultipartFile接口类型 的参数file(前端)上传到程序中的文件就是被封装在该参数中 ( MultipartFile接口 )的。org.springframework. web mutipart.MultipartFile接口提供获取上传文件文件名称等方法,这些方法及其说明如下表示 :

    MultipartFile接口中的主要方法 :

    方法说明
    byte[ ] getBytes( )字节数组 形式 返回文件内容
    String getContentType( )返回 文件内容类型
    InputStream getInputStream( )读取文件内容返回一个InputStream流
    String getName( )获取 多部件form表单参数名称
    String getOriginalFilename( )获取 上传文件初始化名
    long getSize( )获取 上传文件大小单位字节
    boolean isEmpty( )判断 上传的文件是否为空
    void transferTo( File file )上传的文件 保存目标目录下
    ps :
    方法 中的 File参数本质上传文件存储地址信息因为 MultipartFile接口代表上传文件本身

1.3 文件上传“应用案例” :

文件上传 (存储在“相对路径”)
  • 第一步导入依赖
    SpringMVC所需JAR
    SpringMVC中“文件上传”和“下载”所需JAR

  • 第二步配置具体操作代码文件

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!-- 配置"前端过滤器"--><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--  配置springmvc-config.xml配置文件的位置 (上下文配置位置) --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-config.xml</param-value></init-param><!--  配置启动服务器时加载此配置文件,加载此servlet --><load-on-startup>1</load-on-startup></servlet><!--  配置Servlet的Mapper映射  --><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>
    

    springmvc-config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--  定义“组件扫描”,指定需要扫描的包,让注解生效 --><mvc:component-scan base-package="com.myh.controller"/><!--  配置“视图解析器” : 对于“返回视图”的操作有便利  --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--  设置前缀   --><property name="prefix" value="/WEB-INF/jsp/"/><!--  设置后缀   --><property name="suffix" value=".jsp"/></bean><!--  配置文件上传解析器 : 多部件解析器 : MultipleResolver  --><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!--  设置请求编码格式   --><property name="defaultEncoding" value="UTF-8"/></bean></beans>
    

    FileUploadController.java

    package com.myh.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    import java.util.UUID;/*** 文件上传 (相对路径)*/
    @Controller
    public class FileUploadController {/*** 执行文件上传*/@RequestMapping("/fileUpload")public String handldFormUpload(@RequestParam("username") String username , @RequestParam("file") List<MultipartFile> uploadfiles,HttpServletRequest request) {//判断所上传的文件是否存在if (!uploadfiles.isEmpty() && uploadfiles.size() > 0) {//循环输出上传的文件for (MultipartFile multipartFile : uploadfiles) {//获得上传文件的原始名String originalFilename = multipartFile.getOriginalFilename();/*** 设置上传文件的"保存地址"*///从HTTP请求对象中获取ServletContext对象,然后使用ServletContext对象的.getRealPath()方法来获得“真实路径”。String dirPath = request.getServletContext().getRealPath("/upLoadFile/"); //会在out目录下的打包的项目的“根目录”下创建该文件夹,用于存储文件File filePath = new File(dirPath);//如果保存文件的地址不存在,则先创建目录if (!filePath.exists()) {filePath.mkdirs(); //创建目录(创建文件夹)}//使用UUID重新命名上传的文件名称(上传人_uuid_原始文件名称)/*UUID.randomUUID() 是Java中的一个方法,用于生成一个随机的、唯一的标识符(Universally Unique Identifier,简称UUID)*/String newFilename = username + UUID.randomUUID() + originalFilename;try {//使用MultipartFile接口的 transferTo()方法将文件上传到指定位置/*transferTo(File file) : 该方法中的参数本质上为“上传文件”的存储地址信息,因为multipartFile接口就代表“上传文件本身”*/multipartFile.transferTo(new File(dirPath + newFilename));System.out.println(new File(dirPath + newFilename));} catch (IOException e) {e.printStackTrace();return "error"; //返回错误页面}}//跳转成功页面return "success";} else {return "error";}}
    }
    

    上述代码中,使用注解方式定义了一个控制器类,并在类中定义了执行文件上传方法 :
    handleFormUpload( )在handleFormUpload( )方法参数中使用了List<MultipartFile>集合类型
    接收用户上传的文件,然后判断所上传文件是否存在。如果存在,则继续执行上传操作,在通过MultipartFile接口transferTo( )方法将上传文件保存用户指定的目录位置 ,会跳转到success.jsp页面;如果文件不存在或者上传失败,则跳转到error.jsp页面

    注意点
    此处 文件 存储的路径相对路径 ,即 /upLoadFile/ : 如果该文件夹还没存在,会先在 项目打包后根目录 创建一个 文件夹 : upLoadFile, 然后将 上传的文件 存储到该文件夹中) ,upLoadFile文件夹 (是 相对路径 ) 位置展示如下图所示
    在这里插入图片描述


    FileUpload.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>文件上传</title><script>//判断是否填写上传人并已选择上传文件function check() {var username = document.getElementById("username").value;var file = document.getElementById("file").value;if (username == "") {alert("请填写上传人!");return false;}if (file.length == 0 || file == "") {alert("请选择上传文件!");return false;}return true;}</script>
    </head>
    <body>
    <%--οnsubmit="return check()" : 只有check()方法的返回值为true,才会正常提交表单(才会访问url)
    --%>
    <form action="${pageContext.request.contextPath}/fileUpload" enctype="multipart/form-data" method="post" onsubmit="return check()">上传人:<input type="text" id="username" name="username"></br>请选择文件:<input type="file" id="file" name="file" multiple="multiple"></br><input type="submit" value="上传"></form>
    </body>
    </html>
    

    文件中,编写了一个用于文件上传fom表单,该表单可以填写上传人上传文件,当单击“上传” 按钮时,会先执行ceck方法检查上传 人文本框文件选择框中内容是否为空只有填写了上传人并选择了需要上传的文件后,才能正常提交表单;否则表单将不会提交,并给相应提示信息οnsubmit="return check() : 只有方法中返回值为true才会提交表单)。 提交表单后,会以POST方式提交到一个以”/fileUpload”结尾的请求中。


    error.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>error页面</title>
    </head>
    <body>
    error!
    </body>
    </html>
    

    success.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>success页面</title>
    </head>
    <body>
    ok!
    </body>
    </html>
    

    项目发布Tomcat服务器中并启动,在浏览器中访问地址 : http://localhost:8080/FileUpload.jsp 其显示效果如下图所示 :

    在这里插入图片描述

    在上面的 上传页面 中,填写 上传人 并选择所要 上传的文件,单击 上传 按钮后就可向后台发送上传请求信息


    在这里插入图片描述


    单击 上传按钮,程序在正确执行后浏览器 就会跳转到 success.jsp 页面,此时查看 项目发布项目 ,即 可发现 在:
    S:\2024项目\SpringMVC中的“文件上传”和“下载”\out\artifacts\SpringMVC_Web_exploded下 ( 能 在idea找到该文件夹,所以 属于“相对路径) 创建了一个名字为 :upLoadFile文件夹,同时 前端上传的文件存储该文件夹 中。在IDEA中查看存储上传文件”的upLoadFile文件夹:

    在这里插入图片描述


    注意点

    需要注意的是 ,upLoadFile文件夹 是在项目的 发布路径 / 打包路径 中,而不是创建的项目所在目录中 :
    在这里插入图片描述

文件上传 (存储在“绝对路径”)
  • 文件上传 (存储在“绝对路径”)实现: 除了 FileUploadController.java 这个文件有不同之外其他的都是相同的。(替换以下代码就是将“文件”存储在“绝对路径”)

    /**
    * 存储的是“绝对路径”,将上传的文件存储在D盘下的upLoadFile3文件夹下
    */
    String dirPath = "D:/upLoadFile3/";
    

    FileUploadController.java :

    package com.myh.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    import java.util.UUID;/*** 文件上传 (绝对路径)*/
    @Controller
    public class FileUploadController2 {/*** 执行文件上传( 文件存储在"绝对路径")*/@RequestMapping("/fileUpload3")public String handldFormUpload(@RequestParam("username") String username , @RequestParam("file") List<MultipartFile> uploadfiles,HttpServletRequest request) {//判断所上传的文件是否存在if (!uploadfiles.isEmpty() && uploadfiles.size() > 0) {//循环输出上传的文件for (MultipartFile multipartFile : uploadfiles) {//获得上传文件的原始名String originalFilename = multipartFile.getOriginalFilename();/*** 存储的是“绝对路径”,将上传的文件存储在D盘下的upLoadFile3文件夹下*/String dirPath = "D:/upLoadFile3/";File filePath = new File(dirPath);//如果保存文件的地址不存在,则先创建目录if (!filePath.exists()) {filePath.mkdirs(); //创建目录(创建文件夹)}//使用UUID重新命名上传的文件名称(上传人_uuid_原始文件名称)/*UUID.randomUUID() 是Java中的一个方法,用于生成一个随机的、唯一的标识符(Universally Unique Identifier,简称UUID)*/String newFilename = username + UUID.randomUUID() + originalFilename;try {//使用MultipartFile接口的 transferTo()方法将文件上传到指定位置/*transferTo(File file) : 该方法中的参数本质上为“上传文件”的存储地址信息,因为multipartFile接口就代表“上传文件本身”*/multipartFile.transferTo(new File(dirPath + newFilename));System.out.println(new File(dirPath + newFilename));} catch (IOException e) {e.printStackTrace();return "error"; //返回错误页面}}//跳转成功页面return "success";} else {return "error";}}
    }
    

二、文件下载

2.1 实现“文件下载” ( “不可”下载“非中文名称”文件 )

文件下载 就是将 文件服务器 中的 文件下载到本机上。在SpringMVC环境中,实现文件下载 大致可分为 如下两个步骤

客户端页面 使用一个 文件下载超链接,该链接href属性 要指定后台文件下载方法 以及 文件名 (需要先在文件下载目录中添加了一个名称为 “1.jpg"的文件 ),具体代码示例如下 :

<a href="${pageContext.request.contextPat}/download?filename=1.jpg"> 文件下载
</a>

在后台 Controller类 中,使用 SpringMVC 提供的 文件下载方法 进行 文件下载SpringMVC提供了一个 ResponseEntity类型对象,使用它可以很方便地定义返回HttpHeaders对象HttpStatus对象,通过对这两个对象的设置,即 可完成下载文件所需的配置信息

文件下载示例代码 如下所示 :

package com.myh.controller;import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;/*** 文件下载
*/
@Controller
public class FileDownLoadController {@RequestMapping("/download")public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,String filename) throws IOException {//指定要下载的文件所在的路径 (即存储文件的路径) --此时用的是“相对路径”String path = request.getServletContext().getRealPath("/upLoadFile/");//创建该对象File file = new File(path + File.separator + filename);//设置"响应头"HttpHeaders headers = new HttpHeaders();//通知浏览器“以下载的方式”打开文件headers.setContentDispositionFormData("attachment", filename);//定义"以流的形式下载"返回文件数据headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);//使用Spring MVC框架的 ResponseEntity对象封装"下载数据"ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);return responseEntity;}
}

fileDownload( )方法 中,首先根据 文件路径 和需要下载的 文件名创建文件对象,然后对 响应头文件下载时的打开方式 以及 下载方式 进行了设置,最后返回 ResponseEntity封装下载结果对象

ResponseEntity对象 有些 类似 前面章节介绍的 @ResponseBody注解,它用于 直接返回结果对象。上面示例中,设置 响应头信息MediaType代表的是Interner Media Type (即互联网媒体类型),也叫作MIME类型, MediaType.APPLICATION_OCTET_STREAM的值为 application/octet-stream,即表示以 二进制流形式下载数据
HttpStatus 类型代表的是Http协议中的状态,示例中的 HttpStatus.OK 表示 200 ,即服务器 已成功处理了请求


启动服务器后访问网址 :http://localhost:8080/FileDownLoad.jsp ,其显示效果如下图所示
在这里插入图片描述

点击“文件下载”链接后,会出现下载提示弹窗如下图所示
在这里插入图片描述

此时,点击“下载”即可下载该文件

2.2 “中文名称”的文件下载 ( “可”下载“中文名称”文件 )

  • 虽然在 实现“文件下载”案例 中能通过 Spring MvC实现了文件下载功能,但 此案例代码 只适用非中名称的文件进行下载,当对中文名称文件进行下载时,因为各个浏览器内部转码机制的不同,就会出现 不同的乱码以及解析异常问题。例如在文件下载目录中添加一个名称为“壁纸.jpg” 的文件,当通过浏览器下载该文件时,下载弹出窗口显示如下图所示 :
    在这里插入图片描述

    上图可以看出,所要下载的文件名称不是壁纸.jpg, 而是“_.jpg", 这就表示 中文文件名称出现了乱码。那么我们要如何解决这种乱码问题呢?

  • 为了 解决浏览器中文件下载中文名称的乱码问题,可以在 前端页面发送请求前对中文名进行统一编码,然后在 后台控制器类对文件名称进行相应的转码,其 具体实现步骤如下 :

    • 下载页面中对中文文件名编码。可以使用ServletAPI中提供的 URLEncoder类 ( URL编码器 )中的 encoder( String s, String enc )方法中文转为UTF-8编码。该方法中 第一个参数表示 需要转码的字符串
      第二个参数表示 编码格式,其具体实现方式如下
      代码所示

      FileDownLoad.jsp :

      <%@ page import="java.net.URLEncoder" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
      <html>
      <head><title>文件下载(下载中文名称文件)</title>
      </head>
      <body>
      <%--<%= URLEncoder.encode("壁纸.jpg","UTF-8") %> : 其作用为:通过URLEncoder(URL编码器)的,encode()方法来对“中文文件名称”进行“转码”
      --%>
      <a href="${pageContext.request.contextPath}/download2?filename=<%= URLEncoder.encode("壁纸.jpg","UTF-8") %>">“中文名称”文件下载
      </a>
      </body>
      </html>
      
    • 修改控制器类FileUploadController 中的fileDownload( )方法,并 增加对文件名进行编码方法,其代码如下所示 :

      FileDownLoadController2.java

      package com.myh.controller;import org.apache.commons.io.FileUtils;
      import org.springframework.http.HttpHeaders;
      import org.springframework.http.HttpStatus;
      import org.springframework.http.MediaType;
      import org.springframework.http.ResponseEntity;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;
      import java.io.File;
      import java.io.IOException;
      import java.io.UnsupportedEncodingException;
      import java.net.URLEncoder;/*** 文件下载 (下载中文名称文件)*/
      @Controller
      public class FileDownLoadController2 {@RequestMapping("/download2")public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,String filename) throws IOException {//指定要下载的文件所在的路径 (即存储文件的路径) --此时用的是“相对路径”String path = request.getServletContext().getRealPath("/upLoadFile/");//创建该文件对象File file = new File(path + File.separator + filename);/*** 对文件名编码,防止中文文件乱码*/filename = this.getFilename(request,filename);//设置"响应头"HttpHeaders headers = new HttpHeaders();//通知浏览器“以下载的方式”打开文件headers.setContentDispositionFormData("attachment", filename);//定义以流的形式下载返回文件数据headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);//使用Spring MVC框架的 ResponseEntity对象封装"下载数据"ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);return responseEntity;}/***  根据浏览器的不同编码进行设置,返回编码后的文件名*/private String getFilename(HttpServletRequest request, String filename) throws UnsupportedEncodingException {//IE不同版本User-Agent中出现的关键词String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};//获取请求头代理信息String userAgent = request.getHeader("User-Agent");for (String keyWord : IEBrowserKeyWords) {if (userAgent.contains(keyWord)) {//IE内核浏览器,统一为UTF-8编码显示return URLEncoder.encode(filename, "UTF-8");}}//火狐等其他浏览器统一为ISO-8859-1编码显示return new String(filename.getBytes("UTF-8"), "ISO-8859-1");}
      }
      

      在方法getFilename( )中,由于IE浏览器文件编码上其他浏览器的方式不同,所以在中文编码设置上IE浏览器设置为UTF-8编码,而火狐等其他浏览器设置ISO-8859-1编码。另外由于不同版本IE浏览器,请求代理User-Agent中的关键字也略有不同,所以在判断IE浏览器时,需要特别意User-Agent中关键字

      再次进行中文名文件下载测试如下图所示
      在这里插入图片描述

相关文章:

SpringMVC | SpringMVC中的 “文件上传和下载”

目录: 一、文件上传1.1 文件上传“概述”1.2 文件上传“具体配置” :“前端”中配置“文件上传” ( type“file” 满足3个条件 )“后端”中配置“文件上传” ( 配置id为“CommonsMultipartResolver”的bean 配置“文件上传”的“约束条件” 通过“MultipartFile接口”参数接…...

JVM快速入门(2)HotSpot和堆、新生区、永久区、堆内存调优、JProfiler工具分析OOM原因、GC(垃圾回收)、JVM经典面试笔试题整理

5.6 HotSpot和堆 5.6.1 Hotspot 三种JVM&#xff1a; Sun公司&#xff0c;HotspotBEA&#xff0c;JRockitIBM&#xff0c;J9 VM&#xff0c;号称是世界上最快的Java虚拟机 我们一般学习的是&#xff1a;HotSpot 5.6.2 堆 Heap&#xff0c;一个JVM只有一个堆内存&#xff0c…...

我的风采——android studio

目录 实现“我的风采”页面要求理论代码生成apk文件 实现“我的风采”页面 要求 要求利用’java框架的边框布局实现“找的风采 ”页而&#xff0c;其中中间为你的生活照&#xff0c;左右和下面为按钮&#xff0c;上面为标签 理论 Java GUI编程是Java程序设计的重要组成部分…...

BMS设计中的短路保护和MOSFET选型(上)

电池管理系统&#xff08;BMS&#xff09;是一种能够对电池进行监控和管理的电子装备&#xff0c;是电池与用户之间的纽带。通过对电压、电流、温度以及SOC等数据采集&#xff0c;计算进而控制电池的充放电过程&#xff0c;主要就是为了能够提高电池的利用率&#xff0c;防止电…...

用go实现一个任务调度类 (泛型)

用go实现一个任务调度类 &#xff08;泛型&#xff09; 源码地址&#xff1a; https://github.com/robinfoxnan/BirdTalkServer/blob/main/server/core/workmanager.go 1.概述 实现了一个简单的任务管理系统&#xff0c;允许用户定义任务和工作者&#xff0c;并将任务分配给…...

ansible 管理工具以及常用模块

一、前期准备 1、安装 yum install ansible 如果yum源没有ansible&#xff0c;需要提前配置yum源&#xff1a; mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup wget -O…...

javaSSM公司招聘管理系统IDEA开发mysql数据库web结构计算机java编程maven项目

一、源码特点 IDEA开发SSM公司招聘管理系统是一套完善的完整企业内部系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;MAVEN方式加 载&#xff0c;系统具有完整的源代码和…...

蓝桥杯day11刷题日记

P8615 [蓝桥杯 2014 国 C] 拼接平方数 思路&#xff1a;先把数据范围内的平方数打上标记&#xff0c;然后就是遍历这个区间&#xff0c;转成字符串&#xff08;好拆数据&#xff09;&#xff0c;用substr拆开数据&#xff0c;再强转成整数类型&#xff0c;最后查看拆开的数据是…...

IDEA, Pycharm, Goland控制台乱码

IDEA, Pycharm, Goland控制台乱码 问题描述: 控制台出现&#xfffd;&#xfffd;&#xfffd;&#xfffd;等乱码 复现频率: 总是 解决方案: 以IDEA为例 添加 -Dfile.encodingUTF-8位置 idea64.exe.vmoptions 在安装idea的bin目录idea.vmoptions idea客户端 示意图...

JavaScript单元测试jasmine学习(一)

介绍&#xff1a; jasmine是用于测试JavaScript的一种测试框架,BDD(Behavior Driven Development)行为驱动开发。不依赖于任何其他JavaScript框架&#xff0c;也不需要DOM 准备工作&#xff1a; 1. 首先添加jasmine到自己的项目中 npm install --save-dev jasmine 2. 在项目…...

108、3D Gaussian Splatting for Real-Time Radiance Field Rendering

简介 官网 更少训练时间的同时实现最先进的视觉质量&#xff0c;能在1080p分辨率下实现高质量的实时(≥30 fps)新视图合成 NeRF使用隐式场景表示&#xff0c;体素&#xff0c;点云等属于显示建模方法&#xff0c;3DGS就是显示辐射场。它用3D高斯作为灵活高效的表示方法&…...

PHP之CURL和Socket

文章目录 一、CURL1.基本流程&#xff08;1&#xff09;初始化&#xff08;2&#xff09;向服务器发送请求&#xff08;3&#xff09;向服务器发送请求&#xff08;4&#xff09;关闭curl 2.CURLOPT参数记得写一个文件curl上传的例子记得写一个json上传的例子3.CURL批处理 二、…...

【Web】NKCTF 2024 个人wp(部分)

目录 my first cms 全世界最简单的CTF attack_tacooooo 属实太菜了&#xff0c;3/4 my first cms 一眼搜版本2.2.19 CVE -CVE-2024-27622 GitHub - capture0x/CMSMadeSimple 访问/admin/login.php 爆出弱口令&#xff0c;后台登录 admin Admin123 Extensions > User D…...

QT常见布局器使用

布局简介 为什么要布局&#xff1f;通过布局拖动不影响鼠标拖动窗口的效果等优点.QT设计器布局比较固定&#xff0c;不方便后期修改和维护&#xff1b;在Qt里面布局分为四个大类 &#xff1a; 盒子布局&#xff1a;QBoxLayout 网格布局&#xff1a;QGridLayout 表单布局&am…...

政安晨:【深度学习部署】—— TensorFlow Extended(TFX)介绍

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras实战演绎机器学习 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 前言 TensorFlow Extended&#xff08;TFX&a…...

宝石与石头

宝石与石头 链接:https://leetcode.cn/problems/jewels-and-stones/description/ 给你⼀个字符串 jewels 代表石头中宝石的类型&#xff0c;另有⼀个字符串 stones 代表你拥有的石头。 stones 中每个字符代表了⼀种你拥有的石头的类型&#xff0c;你想知道你拥有的石头中有多…...

【Vue3之computed属性(四)】

文章目录 前言一、computed属性有缓存二、使用方法三、修改全名 前言 理解computed属性&#xff0c;实现输入姓和名得出全名并双向绑定&#xff0c;区分单向绑定和双向绑定。测试computed属性和方法的区别 一、computed属性有缓存 先引入computed&#xff0c;写箭头函数定义并…...

生产力工具|安装更新R软件(R、studio)

内容介绍&#xff1a; 安装R软件&#xff1a; 下载 R X64 3.5.1: 访问官方R网站 https://cran.r-project.org/。选择适合Windows版本的安装包。将安装包下载到您的计算机。 本地安装: 运行下载的“R-3.5.1-win.exe”文件。按照安装向导&#xff0c;选择安装路径&#xff0c;取消…...

ffmpeg实现媒体流解码

本期主要讲解怎么将MP4媒体流的视频解码为yuv,音频解码为pcm数据;在此之前我们要先了解解复用和复用的概念; 解复用:像mp4是由音频和视频组成的(其他内容流除外);将MP4的流拆分成视频流(h264或h265等)和音频流(AAC或mp3等); 复用:就是将音频和视频打包成MP4或者fl…...

面试题 之 react

1.说说对react的理解 1️⃣是什么 React是用于构建用户界面的 JavaScript 库,遵循组件设计模式、声明式编程范式和函数式编程概念&#xff0c;更高效使用虚拟 DOM 来有效地操作 DOM &#xff0c;遵循从高阶组件到低阶组件的单向数据流。 react 类组件使用一个名为 render() 的方…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...