zoukankan      html  css  js  c++  java
  • 第17天 笔记 文件上传下载

    第17天 笔记 文件上传下载

    1. 使用过滤器的步骤
    1. filter执行顺序如何确定,如果有两个过滤器都拦截同一个请求。

    3)Filter接口中的doFilter方法和FilterChain接口中的doFilter的区别

    今日任务:

    1. 文件上传
    2. 文件下载

    课堂笔记

    1、文件上传

    1.1、文件上传介绍

        生活中遇到的文件上传技术实现?

        网盘,头像,邮件的附件,朋友圈(日报)

        文件上传(B/S)架构和基本原理?

        B/S架构是浏览器和服务器架构,浏览器发出请求,服务器给出响应。

        C/S架构是客户端和服务器架构,客户端发出请求,服务器给出相应。

    历史:以前都是喜欢客户端和服务器,第一,获取用户的计算机数据方便,对用户的控制力强,方便培养用户习惯,自定义网络传输的协议。

    客户端,占用计算机内存和硬盘,客户端,使用协议太多,安全性不高,所以诞生浏览器

    浏览器设计宗旨:丢弃客户端,占用内存和硬盘,统一协议,安全性高,使用浏览器,只需要更新浏览器即可。

    使用B/S架构来做文件上传的思路?

    1. 给用户一个功能,让他自己可以去选择要上传的文件
    2. 需要让用户可以发送当前被上传文件的数据,而且,还要告诉服务器,这是文件上传的请求
    3. 接收请求,使用IO技术读取请求中被上传文件的数据
    4. 将数据保存到服务器的硬盘上。

    1.2、文件上传页面实现和注意细节(重点:必须掌握)

        第一个问题:如何告诉浏览器,让用户选择要上传的文件?

        <!-- 演示在页面中显示选择文件上传的按钮 -->

         请选择要被上传的文件:<input type="file" name="upload">

        第二问题:如何提交数据?

        GET请求:GET请求数据长度有限制(1KB),所以不能用。

        POST请求:就用这个,这个好,数据长度没有限制。

        

        使用POST请求,一般是用form表单,设置请求方式为POST

        第三个问题:如何通知服务器,这是一个文件上传的请求?

        设置enctype(这是form表单中属性)的值为:multipart/form-data

    思考:

    文件上传的时候,我们数据,都是二进制的数据,不应该被编码

    普通的请求,数据到服务器之后,我们需要的都是文本内容,需要被存入数据库,所以需要编码

    MIME类型:文件的媒体类型,.Jpg .avi .rmvb .mp4 .3gp

    现在很多视频软件,它的后缀名都是当前软件名称,爱奇艺,.aqy .itcast

    我的视频,提供下载功能,也只能用自己的播放器看。

    浏览器代码实现:

    <!-- 设置一个form表单,设置请求方式为post,保证发送数据没有长度限制 -->

    <!-- 设置enctype="multipart/form-data" 用来提示当前是文件上传请求 -->

    <form action="${root }/upload1" method="post" enctype="multipart/form-data">

            <!-- 设置一个按钮,让用户可以选择要被上传的文件 -->

            请选择要上传的文件:<input type="file" name="upload">

            <input type="submit" value="确认上传">

    </form>

    小结(文件上传浏览器端实现):

    1. 设置一个<input type="file" name="upload">,让用户去选择要被上传的文件
    2. 设置一个form表单,method="POST"(让文件上传数据长度没有限制) ,enctype=" multipart/form-data"(告诉服务器这是一个文件上传的请求,数据不要编码)
    3. 设置一个提交按钮,提交请求。

    文件上传浏览器效果:

    1.3、文件上传的服务器简单实现

    上传的数据在哪里?

    浏览器的请求发送过来之后,服务器创建一个请求对象,将所有的请求数据,都封装在request对象中,

    所以文件上传的数据,肯定在request对象中。

    文件上传代码示例:

    package cn.itcast.upload;

     

    import java.io.IOException;

     

    import javax.servlet.ServletException;

    import javax.servlet.ServletInputStream;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

     

    public class UploadServelt1 extends HttpServlet {

     

        public void doGet(HttpServletRequest request, HttpServletResponse response)

                throws ServletException, IOException {

     

            //文件上传请求的数据,肯定在request

            //第一步:获取上传的请求流

            ServletInputStream in = request.getInputStream();

            //第二步:将数据打印在控制台上

            int temp = 0;

            while((temp = in.read()) != -1){

                System.out.write(temp);

            }

        }

     

        public void doPost(HttpServletRequest request, HttpServletResponse response)

                throws ServletException, IOException {

            doGet(request, response);

        }

     

    }

    基本的IO操作:

        File : 文件和文件夹的操作

        Inputstream : 读取文件数据

        Outputstream:输出数据

    文件上传原理分析:

    -----------------------------15767295007281,一个数据的分隔符,

    这个分隔符,将不同input输入框中的数据,进行分隔。

    text/plain enctype(MIME类型),都是指文件的媒体类型

    .avi .mp3 .txt .jpg 以后缀名的方式显示的媒体格式;

    后缀名对应的文件媒体格式,text/plain这样的方式描述,如果需要找到后缀名相关的文件媒体格式

    注意:文件名的后缀名和文件的媒体格式的对应关系

    可以通过tomcat服务器目录下的conf文件夹中的web.xml文件来查询,查询搜索mime-mapping就可以了

    重点:被上传文件的真实数据,其实都在text/plain这一行后,隔一行开始,一直到分隔符结束。

    2、Apache的commons-fileupload工具jar包介绍

    2.1、commons-fileupload介绍

        

    下载:http://commons.apache.org/proper/commons-fileupload/

        

    需要使用fileupload组件完成文件上传,这时还需要下载commons-io 的jar包。

        

    解压,把jar包复制到项目中。

    flieUpload工具的目录结构:

        

    2.2、fileupload的文件上传解析流程图

    因为,文件上传,必须,完成所有步骤才能看到效果,所以,先完成文件上传,然后,分许其中的对象和步骤。

    普通字段: <input type="text" name="desc">——普通文本框

    上传文件1:<input type="file" name="upload">——上传文件的组件

    上传文件2:<input type="file" name="upload">——上传文件的组件

    ServletFIleUpload: 它是解析文件上传数据的核心对象

    DiskFileItemFactory: 它是帮助ServletFIleUpload一起解析request的对象,作用:将所有input输入框中的数据,解析,成一个一个的FileItem对象

    FileItem:封装了所有input输入框中数据的对象

    以上三个对象,是我们核心对象。

    过程:

    1. 创建一个DiskFileItemFactory,将这个对象绑定到ServletFIleUpload
    2. 使用ServletFIleUpload对象,解析request
    3. 解析完request,获取的是一个一个的fileItem对象(input输入框中内容)

    2.3、fileupload的实现演示(重点:必须掌握=必须自己代码写出来)

    package cn.itcast.web;

     

    import java.io.File;

    import java.io.IOException;

    import java.util.List;

     

    import javax.servlet.ServletException;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

     

    import org.apache.commons.fileupload.FileItem;

    import org.apache.commons.fileupload.FileUploadException;

    import org.apache.commons.fileupload.disk.DiskFileItemFactory;

    import org.apache.commons.fileupload.servlet.ServletFileUpload;

     

    public class UploadServlet2 extends HttpServlet {

     

        public void doGet(HttpServletRequest request, HttpServletResponse response)

                throws ServletException, IOException {

     

            //需求:完成文件上传

            

            //1    创建一个DiskFileItemFactory,将这个对象绑定到ServletFIleUpload

            DiskFileItemFactory factory = new DiskFileItemFactory();

            ServletFileUpload fileUpload = new ServletFileUpload(factory);

            //2    使用ServletFIleUpload对象,解析request

            try {

                //3    解析完request,获取的是一个一个的fileItem对象(input输入框中内容)

                //解析动作已经完成。

                List<FileItem> list = fileUpload.parseRequest(request);

                

                //4遍历循环list集合,根据不同fileItem对象,不同处理

                for (FileItem item : list) {

                    //item.isFormField() 判断当前是否是一个普通字段:true,是 false 不是

                    if(item.isFormField()){

                        //表示普通字段

                        System.out.println(item.getFieldName());

                        System.out.println(item.getString());

                    }else{

                        //表示文件上传

                        //5将被上传的文件数据,保存到服务器的硬盘上

                        //将被上传的文件统一保存在upload文件夹中

                        //C:/apache-tomcat-7.0.52/webapps/day17/upload

                        String realPath = this.getServletContext().getRealPath("/upload");

                        //6)获取文件名

                        String fileName = item.getName();

                        File file = new File(realPath,fileName);

                        try {

                            item.write(file);

                        } catch (Exception e) {

                            e.printStackTrace();

                        }

                    }

                }

            } catch (FileUploadException e) {

                e.printStackTrace();

            }

        }

     

        public void doPost(HttpServletRequest request, HttpServletResponse response)

                throws ServletException, IOException {

            doGet(request, response);

        }

     

    }

    3、commons-fileupload 详解(对核心类的API介绍)

    3.1、DiskFileItemFactory类(磁盘的文件项工厂类)

    3.1.1、设置缓存大小

    方法截图:

    为什么要设置缓存大小?

    缓存越大,效率越高。

    缓存:内存中开辟的一个存储数据的空间

    内存读取效率高于硬盘,设置缓存,提高读取效率,缓存越大,效率越高。

    代码操作:

    1. 设置临时文件存储位置

    方法截图:

    为什么要设置临时文件存储位置?

    被上传文件的大小,一定会出现超出缓存大小的情况,这些超出的数据,也需要找一个地方存储(临时)起来。

    相当于:卡车拉了一堆砖头,需要一个临时的场地,存放这些砖头,为了后期,在建筑房子(形成文件),使用这些砖头。

    总结:1)数据必然会超出缓存

         2)数据必须在形成文件之前临时存储

    代码操作:

    如何获取当前操作系统的临时文件存储位置?

    System类

    代码演示:

    package cn.itcast.utils;

     

    public class TestUtils {

     

        public static void main(String[] args) {

            //C:UserswjnAppDataLocalTemp

            System.out.println(System.getProperty("java.io.tmpdir"));

        }

    }

    3.2、ServletFileUpload类

    3.2.1、parseRequest方法

    方法截图:

    定义:解析request对象,获取文件上传的数据的方法

    代码操作:

    3.2.2、isMultipartContent方法

    方法截图:

    定义:判断当前请求,是否,是一个文件上传的请求

    代码操作:

    //如果当前请求,不是文件上传

            boolean b = ServletFileUpload.isMultipartContent(request);

            //b true:表示是文件上传,false:不是文件上传

            if(!b){

                //不是文件上传

                response.sendRedirect(request.getContextPath());

                return;

            }

    3.2.3、setHeaderEncoding方法

    方法截图:

    定义:解决中文文件名乱码问题

    代码操作:

            

    3.3、FileItem类

    3.3.1、isFormField方法

    方法截图:

    定义:判断当前input输入框是否是一个普通字段,true,是,false,不是

    代码操作:

    3.3.2、getFieldName方法

    方法截图:

    定义:获取input输入框中name属性值

    代码操作:

    3.3.3、getString方法

    方法截图:

    定义:获取input输入框中,用户输入的值(value值)的方法

    代码操作:

    3.3.4、getName方法

    方法截图:

    定义:获取被上传文件的文件名

    代码操作:

    3.3.5、getInputStream方法(不推荐使用)

    方法截图:

    定义:

    为什么不推荐使用getInputStream?

    如果使用这个方法,先获取输入流,在获取输出流,继续写IO代码,代码太过繁琐,推荐使用原有的方法

    item.write(new File(realPath,fileName));

    代码操作:

    //获取输入流

    //                        InputStream in = item.getInputStream();

    //                        //获取输出流

    //                        FileOutputStream out = new FileOutputStream(new File(realPath,fileName));

    //                        //设置缓存区

    //                        byte[] buf = new byte[1024];

    //                        int len = 0;

    //                        while( (len = in.read(buf)) != -1 ){

    //                            out.write(buf,0,len);

    //                        }

    3.3.6、delete方法

    方法截图:

    定义:删除临时文件的方法

    临时文件会自动删除(item.write()),但是,如果发生异常,临时文件有可能没有删出,调用删除方法

    代码操作:

    4、多文件上传

    4.1、浏览器端js实现

    需求:让用户自己决定上传文件的input输入框的个数

    思路:

    1. 提供一个功能给用户,让用户可以自己去添加input输入框
    2. 提供一个功能给用户,让用户可以自己去删除input输入框
    3. 提交数据按钮

    实现:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

    <c:set var="root" value="${pageContext.request.contextPath }"/>

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

    <html>

    <head>

     

    <title>My JSP 'index.jsp' starting page</title>

        <meta http-equiv="pragma" content="no-cache">

        <meta http-equiv="cache-control" content="no-cache">

        <meta http-equiv="expires" content="0">

        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

        <meta http-equiv="description" content="This is my page">

        <script type="text/javascript">

            //用户自己添加input,用户点击一下,创建一个input

            function _addInput(){

                //创建一个input输入框

                var _input = document.createElement("input");

                //设置文件上传相关属性

                _input.setAttribute("type", "file");

                _input.setAttribute("name", "upload");

                //input标签存入div中(id="_un"

                var _div = document.getElementById("_un");

                _div.appendChild(_input);

                  

                  

                

                

                //再提供一个删除的按钮:点击一个删除按钮,删除一个input输入框

                var _delete = document.createElement("input");

                //设置删除按钮的相关属性

                _delete.setAttribute("type", "button");

                _delete.setAttribute("value", "删除");

                //设置删除按钮的onclick事件,事件(启动一个js函数,执行删除操作)

                _delete.onclick = function(){

                    //执行删除的操作

                    //删除的内容有:文件上传输入框,删除按钮本身,换行符

                    //删除操作由父标签执行

                    //this:代表了当前这个标签对象_delete

                    var _f = this.parentNode;

                    //删除文件上传输入框,先获取当前元素的前一个元素

                    var _p = this.previousSibling;

                    _f.removeChild(_p);

                    

                    //删除换行符,先获取当前元素的后一个元素

                    var _n = this.nextSibling;

                    _f.removeChild(_n);

                    

                    //自杀

                    _f.removeChild(this);

                    

                };

                

                _div.appendChild(_delete);

                

                //在每一个input输入框之后,加上一个换行符

                var _br = document.createElement("br");

                _div.appendChild(_br);

            }

          

        

        </script>

    </head>

     

    <body>

    <!-- 设置一个按钮,用来启动js函数,创建文件上传的input输入框 -->

    <input type="button" value="添加文件上传" onclick="_addInput();"><br/>

    <form action="${root }/upload3" method="post" enctype="multipart/form-data">

        文件描述:<input type="text" name="desc"><br/>

    <!-- 演示在页面中显示选择文件上传的按钮 -->

         请选择要被上传的文件:<input type="file" name="upload"><br/>

         <!-- 当前这个div的位置,就是input标签要存放的位置,那么input标签,只要存放在div中,就是放对了位置 -->

         <div id="_un">

         </div>

         <!-- 不要忘了添加表单的提交按钮 -->

         <input type="submit" value="文件上传">

    </form>

    </body>

     

     

     

    </html>

    在js变量命名时,加上下划线,是为了防止和js中本身全局变量或者函数起冲突。

    4.2多文件上传问题

    4.2.1、文件重名

    重名的原因:

    每次上传文件的时候,因为文件名相同,所以后上传的文件覆盖前一个文件。

    解决方案(学生讨论15分钟,每个小组尽可能多的提供解决方案):

    方案一:用户ip-文件名-(1).zip

    文件名命名方式:使用用户id 加上 文件名 加上数字(文件出现多少次,数据就是几)

    用户名如果保证用户名,每个都不同

    IP 不是每个用户都有一个IP的,在局域网范围内,对外的IP是同一个。

    如果有重复的文件名,在原来的文件名上,加上数字,每出现一次,加一。

    不能擅自压缩用户的数据,那么用户重新从网盘下载数据的时候,发现文件后缀名不同。

    方案二:添加当前文件的最后修改时间,文件的大小,文件前几KB的数据

    方案三:UUID,可以解决

    方案四:文件绝对路径+用户名 进行拼接 作为新的文件名

    不可取,绝对路径会出现重复,而且文件上传只有IE Edge浏览器上传文件,才会带上绝对路径。

    上传文件的时候,不适合将文件的绝对路径显示出来,不太安全。

    方案五:判断文件名是否相同 如果相同添加数字区别

    场景:当前upload文件夹中,有10W文件,那么每做一次文件上传,都要进行10W次循环和判断,这样非常消耗系统性能,这个方案理论成立,实际执行,有问题

    方案六:mac加时间

    Mac:所有电子设备的物理地址,理论上,每个设备都是唯一的,但是,会出现修改地址的情况

    注意:修改文件名的权限,应该,保存在服务器中,不应该将权限放给用户。

    用户的唯一性识别:保证使用当前手机的是一个真实的人。保证mac地址是可以获取的(保证非法用户无法通过购买大两手机号进行注册),也不行,安卓或者ios的模拟器

    方案七:毫秒值

    双十一:一秒钟处理订单量,上百万的,同理,如果出现极端情况,在同一毫秒也会出现同名文件上传,那么也会出现问题。

    注意:在考虑制作系统功能的时候,有时,需要考虑极端情况。

    方案八:hashcode

    同名的文件,他们的文件名计算出来的hashcode,应该是同样的,方案不可取。

    方案九:随机数

    比如:十个随机数,执行11次,就可能出现重复,所以不可取。

    方案十:上传检查,如果重复,则返回,让用户重命名

    用户操作复杂,不可取。

    文件上传,先检查文件名,如果重复,让用户重写书写文件(注意:这个时候,让用户重命名,一定要给出明确的提示)。

    例如:注册游戏,张三已经被注册,提示用户如果你要注册一个张三,(你可以用户名变成张三2333),

    方案十一:不作判断,所有文件都加

    每个文件上传后,获取文件名,然后直接添加一串数字(每次文件上传完成之后,数字加一)

    嘿嘿嘿1.txt

    嘿嘿嘿2.txt

    嘿嘿嘿3.txt

    BigInteger

    需要数据的字段长度,可变(动态改变)

    注意:在数据存储的时候,要注意当前数据不能超过,数据库字段的长度限制

    注意:每次文件上传完成之后,数字加一,需要服务器之间数据同步,不然,肯定会出现重复

    重名问题解决方案

    UUID.randomUUID()这个方法就会生成一个唯一的字符串标识,不会重复。可以作为我们文件名使用。

    代码演示:

    4.3、目录分离

    目录分离需求:

    因为用户上传的文件,日积月累,文件量太大,导致打开一个文件夹的时候,需要时间太长

    所以,我们需要将文件存放在不同的文件夹中。

    场景:比如一个文件夹中,有1个文件,这时打开这个文件夹,需要一秒钟

         比如一个文件夹中,有10W个文件,这时打开这个文件夹,需要10W秒钟

         将10w文件存入1000个文件夹中,打开文件夹的速度,变快了

    4.4、目录分离方案解决

    1)每一个用户有一个专属的文件夹

    2)每一个用户一个专属文件夹的基础上,每天生成一个文件夹,用来存当天上传的文件

        先是有一个张三专属的文件夹,然后,每天创建一个当前的文件夹,专门用来存储,当天上传的文件。

        方案二:由于现在网速的提升,特别是百兆千兆光纤进入普通用户,现在一天上传的文件量,非常大。

    3)使用文件名的哈希值,来计算当前文件应该存储的位置

     

    生成目录的工具类:

    package cn.itcast.utils;

    public class DirUtils {

     

        //根据文件名的哈希值,计算文件该存储的位置

        public static String getDir(String fileName){

            //获取哈希值

            int hashCode = fileName.hashCode();

            //开始计算

            //int类型数据,4个字节,32位,每四位获取一个数字,可以获取8个数字

            //8个数字,都,作为当前文件要存贮的目录

            //获取当前哈希值最低4位,作为一级目录

            int dir1 = hashCode & 15;

            //将哈希值,向右移动4位,更新最低四位

            hashCode = hashCode >> 4;

            //获取第二级目录

            int dir2 = hashCode & 15;

            

            return "/"+dir1+"/"+dir2;

        }

    }

    文件上传servlet修改:

    //修改被上传文件应该储存的位置

    //c:tomcat服务器webappsitcast-upload\upload12

    realPath = realPath + DirUtils.getDir(fileName);

    //在文件上传之前,先判断当前目录是否存在

    File file = new File(realPath);

    if(file.exists()){

    //什么事情都不用干

    }else{

    //不存在,创建目录

        file.mkdirs();

    }

    5、下载介绍

    5.1、超链接下载方式

        文件的下载有2种方式可以完成:

    1、超链接形式:

    <a href="资源的路径" >资源名称</a>

    问题:

    图片和文本资源会直接被解析到浏览器中,不是文件下载。

    中文的文件名点击之后,是404,找不到,中文的文件名被url编码过了导致访问资源路径出错。

     

            2、使用Servlet通知浏览器下载:

                1)浏览器发送请求给服务器(用户要下载的文件名)

                2)服务器加载用户要下载的文件数据。

    3)通知浏览器以下载的方式请求资源

    4)使用IO技术,将数据发送(使用response对象发送数据)

        

        小结:

    1. 先修改页面——发送要下载的文件的文件名

    1. 定位要被下载的文件的位置(获取文件名的时候,处理中文乱码问题)
    2. 设置文件的媒体格式
    3. 解决中文文件名问题(先要判断浏览器,根据不同的浏览器,不同编码处理)
    4. 设置要被下载的文件名
    5. 使用IO技术将数据发送给浏览器(response获取的out输出流,不用手动关闭,自己使用的输入流,需要手动关闭)

    5.2、服务器端写程序下载(重点:必须掌握)

    package cn.itcast.servlet;

     

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.IOException;

    import java.net.URLEncoder;

     

    import javax.servlet.ServletException;

    import javax.servlet.ServletOutputStream;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

     

    import sun.misc.BASE64Encoder;

     

    public class DownloadServlet extends HttpServlet {

     

        public void doGet(HttpServletRequest request, HttpServletResponse response)

                throws ServletException, IOException {

     

            //服务器加载用户要下载的文件数据。

            String realPath = this.getServletContext().getRealPath("/upload");

            //获取当前用户需要下载的文件的文件名

            String parameter = request.getParameter("fileName");

            //处理文件名的中文问题

            String fileName = new String(parameter.getBytes("iso-8859-1"),"utf-8");

            //加载数据

            FileInputStream in = new FileInputStream(new File(realPath,fileName));

            //设置文件的媒体格式

            response.setContentType(getServletContext().getMimeType(fileName));

            //中文的文件名在发送给浏览器之前,需要编码

            //解决编码之前,需要判断浏览器

            String header = request.getHeader("User-Agent");

            if(header.contains("Firefox")){

                //当前浏览器是火狐浏览器,使用base64编码

                BASE64Encoder base64Encoder = new BASE64Encoder();

                fileName = "=?utf-8?B?"    + base64Encoder.encode(fileName.getBytes("utf-8")) + "?=";

                

            }else{

                //其他浏览器,使用URLEncoder编码

                fileName = URLEncoder.encode(fileName,"utf-8");

            }

            //设置要被下载的文件名

            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

            //使用IO技术将数据发送给浏览器

            //使用response向浏览器发送响应

            ServletOutputStream out = response.getOutputStream();

            

            byte[] buf = new byte[1024];

            int len = 0;

            while((len = in.read(buf)) != -1){

                

                out.write(buf, 0, len);

            }

            in.close();

            

        }

     

        public void doPost(HttpServletRequest request, HttpServletResponse response)

                throws ServletException, IOException {

            doGet(request, response);

        }

     

    }

    响应消息头设置:

    Content-Type 设置文件媒体格式

    response.setContentType(getServletContext().getMimeType(filename));

     

    Content-Disposition 设置要被下载的文件名

    response.setHeader("Content-Disposition", "attachment;filename=" + filename);

            

    谷歌浏览器(和主流其他浏览器)中文乱码处理:

            fileName = URLEncoder.encode(fileName,"utf-8");

    火狐下载文件名乱码处理:(先判断是否是火狐浏览器)

    BASE64Encoder base64Encoder = new BASE64Encoder();

    filename = "=?utf-8?B?"    + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";

     

            注意:如果无法使用BASE64Encoder这个类(无法导入这个包),按一下方式解决。

    解决方法:按照如下方法设置Eclipse导入%JAVA_HOME%jrelib目录下的rt.jar包即可,Project->Properties,选择Java Build Path设置项,再选择Libraries标签,Add External Jars添加%JAVA_HOME%jrelib t.jar就可以使用

    如果还是不行,可以再修改项目的JDK,将JDK版本改成本地安装的JDK版本

            

    如果没有自己的JDK:

    6.作业:

    1)使用fileupload完成文件上传功能(40点积分)

    2)使用js实现多文件上传功能(20点积分)

    3)解决文件重名问题(10点积分)

    4)解决文件目录分离问题(10点积分)

    5)完成文件下载功能(10点积分)

    6)解决文件下载中文乱码问题(10点积分)

  • 相关阅读:
    linux获取日志指定行数范围内的内容
    python解决open()函数、xlrd.open_workbook()函数文件名包含中文,sheet名包含中文报错的问题
    robot framework添加库注意事项
    robot framework取出列表子元素
    Vue 及框架响应式系统原理
    响应式布局和自适应布局的不同
    前端综合学习笔记---异步、ES6/7、Module、Promise同步 vs 异步
    前端综合学习笔记---变量类型、原型链、作用域和闭包
    doT.js模板引擎及基础原理
    Spring Boot入门第五天:使用JSP
  • 原文地址:https://www.cnblogs.com/beyondcj/p/6270902.html
Copyright © 2011-2022 走看看