ZK框架文件下载文件名乱码问题(空格,#截断)解决

版权声明:爱我请告诉我 https://blog.csdn.net/hardly555/article/details/78685362

在Java的web开发中,文件下载功能的文件名文件名乱码问题是经常遇到的。
对于这个问题,不同的浏览器,解决的方法不太一样。
IE的话,通过URLEncoder对filename进行UTF8编码。
而其他的浏览器(firefox、chrome、safari、opera),则要通过字节转换成ISO8859-1了。
所以对此要在后台获取浏览器类型(主要识别是否是IE)从而使用不同的编码方法

    //文件下载
    @SuppressWarnings({ "unchecked", "deprecation" })
    @Command
    public void fileDownLoad() throws UnsupportedEncodingException
    {
        if(checkListitems==null||checkListitems.size()==0)
        {
            Messagebox.show("请选择下载的文件","提示", Messagebox.OK, Messagebox.INFORMATION);
            return;         
        }
        Iterator it=checkListitems.iterator();
        Map<String,Object> selectMap=(Map) it.next();
        String filePath=selectMap.get("file_path")+"";
        String fileExtension=filePath.substring(filePath.lastIndexOf("."));
        String enCodeName=(String)selectMap.get("file_name");
        if(!enCodeName.endsWith(fileExtension))
        {
            enCodeName=enCodeName+fileExtension;
        }
        //文件乱码问题兼容IE
        HttpServletRequest request =(HttpServletRequest) Executions.getCurrent().getNativeRequest();        
        String header = request.getHeader("User-Agent").toUpperCase();
        if (header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE")) {
            enCodeName = URLEncoder.encode(enCodeName, "utf-8");
            enCodeName = enCodeName.replace("+", "%20");    //IE下载文件名空格变+号问题
            enCodeName = enCodeName.replace("#", "%23");    //遇到#截断问题
        } 
        else 
        {
            enCodeName=new String(enCodeName.getBytes("UTF-8"), "ISO-8859-1");
            //enCodeName = enCodeName.replace("#", "%23");//这里设置不成功
        }
        File file=new File(MisUtils.getWebRootDir()+filePath);              
        InputStream is=null;
        try {
            is = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Messagebox.show("未找到对应文件!", "错误", Messagebox.OK, Messagebox.ERROR);
            return;         
        }
        if(file.exists())
        {
            //Filedownload. save(is, null, enCodeName); 
            AMedia media=new AMedia(enCodeName, fileExtension.substring(1), null, is);
            Clients.response(new AuDownload(Executions.getCurrent().getDesktop().getDownloadMediaURI(
                    media, enCodeName).replace("+", "%2B").replace("#", "%23")));
        }
    }

到此IE浏览器可以轻松解决文件名包含#或空格转成+号问题
但是,chrome等浏览器使用的是另外一种编码方式ISO8859-1
这个编码方式并不对+或#编码,导致文件下载时服务器后台还是对+或#当成了特殊的符号处理,从而导致下载文件名不对或被截断。

在此附上相关特殊字符的十六进制编码

url出现了有+,空格,/,?,%,#,&,=等特殊符号的时候,可能在服务器端无法获得正确的参数值,如何是好?
解决办法
将这些字符转化成服务器可以识别的字符,对应关系如下:
URL字符转义
用其它字符替代吧,或用全角的。
+ URL 中+号表示空格 %2B
空格 URL中的空格可以用+号或者编码 %20
/ 分隔目录和子目录 %2F
? 分隔实际的URL和参数 %3F
% 指定特殊字符 %25
# 表示书签 %23
& URL 中指定的参数间的分隔符 %26
= URL 中指定参数的值 %3D

由于利用chrome下载时使用的是ISO-8859-1对#和+并没有编码所以利用Filedownload. save(is, null, enCodeName); 服务器还是对特殊符号解码导致错误
为了解决这个问题需要从新使用新的方法再给特殊字符编码(注意在ISO8859-1编码后把#replace到%23不成功)
解决如下(把filedownload替换成下面代码):

//enCodeName为文件名,第二个参数是文件扩展名如txt,第三个参数是contenType如text/plain可使用null(取默认),第四个是文件的流
AMedia media=new AMedia(enCodeName, fileExtension.substring(1), null, is);
//对download的uri所含有的特殊字符进行替换编码
Clients.response(new AuDownload(Executions.getCurrent().getDesktop().getDownloadMediaURI(
                    media, enCodeName).replace("+", "%2B").replace("#", "%23")));

在这里抛出一个疑问:如果普通的JavaWeb(不是使用ZK)使用非IE下载该如何解决这个问题?(

    response.setHeader("Content-disposition", "attachment; filename=\"" + fileName + "\"");
        response.setHeader("Content-Length", String.valueOf(fileLength));

参考:
http://blog.csdn.net/lisehouniao/article/details/52550539
https://stackoverflow.com/questions/47549771/zk8-filedownload-save-cut-filenames#

感谢ZK的Jean Yen ,在这里在此谢谢您的帮助,祝愿ZK越来越好
Thanks,
Hungly

猜你喜欢

转载自blog.csdn.net/hardly555/article/details/78685362