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 即可。
(配置 id 为 “CommonsMultipartResolver”的bean )
除了配置 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时必须指定该Bean的id为mulipartResolver。
由于 CommonsMultipartResolver 是SpringMVC内部通过 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: Sun公司,HotspotBEA,JRockitIBM,J9 VM,号称是世界上最快的Java虚拟机 我们一般学习的是:HotSpot 5.6.2 堆 Heap,一个JVM只有一个堆内存,…...

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

BMS设计中的短路保护和MOSFET选型(上)
电池管理系统(BMS)是一种能够对电池进行监控和管理的电子装备,是电池与用户之间的纽带。通过对电压、电流、温度以及SOC等数据采集,计算进而控制电池的充放电过程,主要就是为了能够提高电池的利用率,防止电…...
用go实现一个任务调度类 (泛型)
用go实现一个任务调度类 (泛型) 源码地址: https://github.com/robinfoxnan/BirdTalkServer/blob/main/server/core/workmanager.go 1.概述 实现了一个简单的任务管理系统,允许用户定义任务和工作者,并将任务分配给…...
ansible 管理工具以及常用模块
一、前期准备 1、安装 yum install ansible 如果yum源没有ansible,需要提前配置yum源: 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公司招聘管理系统是一套完善的完整企业内部系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发)MAVEN方式加 载,系统具有完整的源代码和…...
蓝桥杯day11刷题日记
P8615 [蓝桥杯 2014 国 C] 拼接平方数 思路:先把数据范围内的平方数打上标记,然后就是遍历这个区间,转成字符串(好拆数据),用substr拆开数据,再强转成整数类型,最后查看拆开的数据是…...

IDEA, Pycharm, Goland控制台乱码
IDEA, Pycharm, Goland控制台乱码 问题描述: 控制台出现����等乱码 复现频率: 总是 解决方案: 以IDEA为例 添加 -Dfile.encodingUTF-8位置 idea64.exe.vmoptions 在安装idea的bin目录idea.vmoptions idea客户端 示意图...
JavaScript单元测试jasmine学习(一)
介绍: jasmine是用于测试JavaScript的一种测试框架,BDD(Behavior Driven Development)行为驱动开发。不依赖于任何其他JavaScript框架,也不需要DOM 准备工作: 1. 首先添加jasmine到自己的项目中 npm install --save-dev jasmine 2. 在项目…...

108、3D Gaussian Splatting for Real-Time Radiance Field Rendering
简介 官网 更少训练时间的同时实现最先进的视觉质量,能在1080p分辨率下实现高质量的实时(≥30 fps)新视图合成 NeRF使用隐式场景表示,体素,点云等属于显示建模方法,3DGS就是显示辐射场。它用3D高斯作为灵活高效的表示方法&…...
PHP之CURL和Socket
文章目录 一、CURL1.基本流程(1)初始化(2)向服务器发送请求(3)向服务器发送请求(4)关闭curl 2.CURLOPT参数记得写一个文件curl上传的例子记得写一个json上传的例子3.CURL批处理 二、…...

【Web】NKCTF 2024 个人wp(部分)
目录 my first cms 全世界最简单的CTF attack_tacooooo 属实太菜了,3/4 my first cms 一眼搜版本2.2.19 CVE -CVE-2024-27622 GitHub - capture0x/CMSMadeSimple 访问/admin/login.php 爆出弱口令,后台登录 admin Admin123 Extensions > User D…...

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

政安晨:【深度学习部署】—— TensorFlow Extended(TFX)介绍
政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras实战演绎机器学习 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 前言 TensorFlow Extended(TFX&a…...
宝石与石头
宝石与石头 链接:https://leetcode.cn/problems/jewels-and-stones/description/ 给你⼀个字符串 jewels 代表石头中宝石的类型,另有⼀个字符串 stones 代表你拥有的石头。 stones 中每个字符代表了⼀种你拥有的石头的类型,你想知道你拥有的石头中有多…...

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

生产力工具|安装更新R软件(R、studio)
内容介绍: 安装R软件: 下载 R X64 3.5.1: 访问官方R网站 https://cran.r-project.org/。选择适合Windows版本的安装包。将安装包下载到您的计算机。 本地安装: 运行下载的“R-3.5.1-win.exe”文件。按照安装向导,选择安装路径,取消…...

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

面试题 之 react
1.说说对react的理解 1️⃣是什么 React是用于构建用户界面的 JavaScript 库,遵循组件设计模式、声明式编程范式和函数式编程概念,更高效使用虚拟 DOM 来有效地操作 DOM ,遵循从高阶组件到低阶组件的单向数据流。 react 类组件使用一个名为 render() 的方…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

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

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

华为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面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

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