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

news2024/11/16 15:53:31

目录:

    • 一、文件上传
      • 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/beans
	http://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/beans
    	http://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中关键字

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1542277.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

综合知识篇21-项目管理考点(2024年软考高级系统架构设计师冲刺知识点总结系列文章)

专栏系列文章: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html案例分析篇00-【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例…

02.percona Toolkit工具pt-archiver命令实践

1.命令作用 Percona Toolkit有的32个命令&#xff0c;可以分为7大类 工具类别 工具命令 工具作用 备注 开发类 pt-duplicate-key-checker 列出并删除重复的索引和外键 pt-online-schema-change 在线修改表结构 pt-query-advisor 分析查询语句&#xff0c;并给出建议&#x…

Docker 笔记(七)--打包软件生成镜像

目录 1. 背景2. 参考3. 文档3.1 使用docker container commit命令构建镜像3.1.1 [Docker官方文档-docker container commit](https://docs.docker.com/reference/cli/docker/container/commit/)Description&#xff08;概述&#xff09;Options&#xff08;选项&#xff09;Exa…

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

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

android Fragment 生命周期 方法调用顺序

文章目录 Introlog 及结论代码 Intro 界面设计&#xff1a;点击左侧按钮&#xff0c;会将右侧 青色的RightFragment 替换成 黄色的AnotherRightFragment&#xff0c;而这两个 Fragment 的生命周期方法都会打印日志。 所以只要看执行结果中的日志&#xff0c;就可以知道 Fragme…

2021年XX省赛职业院校技能大赛”高职组 计算机网络应用赛项 网络构建模块竞赛真题

“2021年XX省赛职业院校技能大赛”高职组 计算机网络应用赛项 网络构建模块竞赛真题 目录 一&#xff0e;考试说明 1 二&#xff0e;模块B网络构建 2 &#xff08;一&#xff09;任务描述 2 &#xff08;二&#xff09;任务清单 9 一&#xff0e;考试说明 本模块比赛时间为…

服务消费微服务

文章目录 1.示意图2.环境搭建1.创建会员消费微服务模块2.删除不必要的两个文件3.检查父子模块的pom.xml文件1.子模块2.父模块 4.pom.xml 添加依赖&#xff08;刷新&#xff09;5.application.yml 配置监听端口和服务名6.com/sun/springcloud/MemberConsumerApplication.java 创…

nodejs+vue高校洗浴管理系统python-flask-django-php

高校洗浴管理系统采用数据库是MySQL。网站的搭建与开发采用了先进的nodejs进行编写&#xff0c;使用了express框架。该系统从两个对象&#xff1a;由管理员和学生来对系统进行设计构建。主要功能包括&#xff1a;个人信息修改&#xff0c;对学生管理、浴室信息、浴室预约、预约…

【算法竞赛进阶指南】0x05 排序

0x05排序 排序基本算法 785. 快速排序 - AcWing题库姑且用这个评测。 1.选择、插入、冒泡 这类排序是基于比较的排序算法&#xff0c;时间复杂度为 选择排序 思路比较简单&#xff0c;就是每一次从后面选出最小的数字来与当前这个数字交换 #include<bits/stdc.h> co…

(一)基于IDEA的JAVA基础7

关系运算符 运算符 含义 范例 结果 等于 12 false &#xff01; 不等于 1&#xff01;2 true > 大于 1>2 false < 小于 …

【协议-HTTPS】

https https是在http协议的基础上&#xff0c;添加了SSL/TLS握手以及数据加密传输&#xff0c;也属于应用层协议。 httpshttp加密认证完整性保护 https交互图&#xff1a; HTTPS的整体过程分为证书验证和数据传输阶段&#xff1a; ① 证书验证阶段 浏览器发起 HTTPS 请求 服务…

如何通过idea搭建一个SpringBoot的Web项目(最基础版)

通过idea搭建一个SpringBoot的Web项目 文章目录 通过idea搭建一个SpringBoot的Web项目一、打开idea&#xff0c;找到 create new project二、创建方式三、配置项目依赖四、新建项目模块五、总结 一、打开idea&#xff0c;找到 create new project 方式1 方式2 二、创建方式 新…

如何使用PHP和RabbitMQ实现消息队列?

前言 今天我们来做个小试验&#xff0c;用PHP和RabbitMQ实现消息队列功能。 前期准备&#xff0c;需要安装好docker、docker-compose的运行环境。 如何使用docker部署php服务_php如何使用docker发布-CSDN博客 一、安装RabbitMQ 1、创建相关目录&#xff0c;执行如下命令。…

linux 通过nvm安装node

我的博客原文&#xff1a;linux 通过nvm安装node 前言 nvm是一个node版本控制的工具&#xff0c;他可以查看可以安装的node版本&#xff0c;安装node&#xff0c;以及切换node版本&#xff0c;传统的node安装&#xff0c;我们是下载压缩包&#xff0c;然后指定环境变量&…

医院预约挂号系统设计与实现|jsp+ Mysql+Java+ Tomcat(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;…

MySQL数据库基本操作(增删改查)与用户授权

前言 SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;是一种用于管理关系数据库系统的语言。SQL的设计目标是提供一种简单、直观的语言&#xff0c;使得用户可以通过编写SQL语句来处理他们想要的数据和操作。 目录 一、结构介绍 1. 查看信…

计算机软件安全

一、软件安全涉及的范围 1.1软件本身的安全保密 软件的本质与特征&#xff1a; 可移植性 寄生性 再生性 可激发性 攻击性 破坏性 …… 知识产权与软件盗版 软件商品交易形式不透明&#xff0c;方式多样&#xff0c;传统商标标识方法不适用&#xff1b; 盗版方法简捷…

Django Ajax

【一】Json 【1】介绍 JSON&#xff08;javascript object otaition&#xff09;是一种轻量级的数据交换格式JSON使用了Javascript的一部分语法来定义其数据格式&#xff0c;但Json是独立于语言的Json采用完全独立于语言的文本格式&#xff0c;使得Json成为理想的数据交互语言…

PCB布线和灌铜

PCB布线和灌铜 综述&#xff1a;本文主要讲述AD软件中PCB布线的步骤和灌铜的操作。 一、PCB布线 1. 连接信号线 点击“N”→“隐藏连接”→“网络”&#xff0c;连接信号线&#xff0c;尽量走线短且尽量少打孔。单击界面下放的“top”和“bottom”可以实现不同层的绘制线路…

51单片机学习笔记——LED闪烁和流水灯

任务分析 首先要知道LED闪烁主要是怎么工作的&#xff0c;闪烁亮灭自然是一下为高一下为低&#xff0c;亮灭的频率则需要延时来进行控制。 上节已经知道了如何点亮那延时如何做呢首先先编写主框架 这样是否可以通过循环将LED灯一直循环闪烁。 以为while一直在循环所以其实是可…