Java servlet下载文件名特殊字符 [英] Java servlet download filename special characters

查看:185
本文介绍了Java servlet下载文件名特殊字符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个简单的文件下载servlet,我无法获得正确的文件名。尝试URLEncoding和MimeEncoding现有答案中看到的文件名,但没有一个工作。



以下片段中的fileData对象包含mime类型,byte []内容而至少需要ISO-8859-2字符集,ISO-8859-1的文件名是不够的。



如何让浏览器显示下载的文件名正确?



这是一个文件名的示例:árvíztűrőtükörfúrógép.xls,它的结果是:árvíztqrptükörfúrógép.xls

  protected void renderMergedOutputModel(Map model,HttpServletRequest req,HttpServletResponse res)throws Exception {

RateDocument fileData =(RateDocument)model.get(command.retval) ;
OutputStream out = res.getOutputStream();
if(fileData!= null){
res.setContentType(fileData.getMime());
String enc =utf-8; //尝试过:ISO-8859-2

String encodedFileName = fileData.getName();
//也尝试过URLencoding和mime编码这个文件名没有成功

res.setCharacterEncoding(enc); //尝试使用和不使用这个
res.setHeader(Content-Disposition,attachment; filename =+ encodedFileName);
res.setContentLength(fileData.getBody()。length);
out.write(fileData.getBody());
} else {
res.setContentType(text / html);
out.write(< html>< head>< / head>< body>错误下载文件< / body>< / html>
.getBytes(res.getCharacterEncoding )));
}
out.flush();
}


解决方案

在我安装的所有浏览器(IE8,FF16,Opera12,Chrome22)。

这是基于这样一个事实,浏览器期望在filename参数中的值,即在浏览器本机编码中编码,如果没有[不同]编码。



通常浏览器的本机编码是utf-8(FireFox,Opera,Chrome)。但是IE的本地编码是Win-1250。



所以如果我们把值放在文件名参数中,这是根据用户浏览器由utf-8 / win-1250编码的应该工作至少,它适用于我。

  String fileName =árvíztűrőtükörfúrógép.xls; 

String userAgent = request.getHeader(user-agent);
boolean isInternetExplorer =(userAgent.indexOf(MSIE)> -1);

尝试{
byte [] fileNameBytes = fileName.getBytes((isInternetExplorer)?(windows-1250):(utf-8))
String dispositionFileName =;
for(byte b:fileNameBytes)dispositionFileName + =(char)(b& 0xff);

String disposition =attachment; filename = \+ dispositionFileName +\;
response.setHeader(Content-disposition,disposition);
} catch(UnsupportedEncodingException ence){
// ... handle exception ...
}

当然,这只是在上面提到的浏览器上进行了测试,我无法保证100%的这一切都可以在任何浏览器中运行。



注意#1(@fallen)
使用URLEncoder.encode()方法是不正确的。尽管方法的名称,它不会将字符串编码为URL编码,但它将编码为表单编码。 (格式编码与URL编码非常相似,在许多情况下它产生相同的结果,但有一些差异,例如空格字符'被编码不同:'+'而不是'%20')



对于正确的URL编码字符串,您应该使用URI类:

  URI uri = new URI(null,null,árvíztűrőtükörfúrógép.xls,null); 
System.out.println(uri.toASCIIString());


I am writing a simple file download servlet and I can't get correct filenames. Tried URLEncoding and MimeEncoding the filename as seen in existing answers, but none of them worked.

The fileData object in the following snippet contains the mime type, the byte[] content and the filename, that needs at least ISO-8859-2 charset, ISO-8859-1 is not enough.

How can I get my browser to display the downloaded filename correctly?

Here is an example of the filename: árvíztűrőtükörfúrógép.xls and it results in: árvíztqrptükörfúrógép.xls

  protected void renderMergedOutputModel(Map model, HttpServletRequest req, HttpServletResponse res) throws Exception {

    RateDocument fileData = (RateDocument) model.get("command.retval");
    OutputStream out = res.getOutputStream();
    if(fileData != null) {
        res.setContentType(fileData.getMime());
        String enc = "utf-8"; //tried also: ISO-8859-2

        String encodedFileName = fileData.getName();
            // also tried URLencoding and mime encoding this filename without success

        res.setCharacterEncoding(enc); //tried with and without this
        res.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName);
        res.setContentLength(fileData.getBody().length);
        out.write(fileData.getBody());
    } else {
        res.setContentType("text/html");
        out.write("<html><head></head><body>Error downloading file</body></html>"
                .getBytes(res.getCharacterEncoding()));
    }
    out.flush();
  }

解决方案

I found out solution that works in all browsers I have installed (IE8, FF16, Opera12, Chrome22).
It's based on the fact, that browsers expect value in filename parameter, that is encoded in browsers native encoding, if no [different] encoding is specified.

Usually browser's native encoding is utf-8 (FireFox, Opera, Chrome). But IE's native encoding is Win-1250.

So if we put value into filename parametr, that is encoded by utf-8/win-1250 according to user's browser, it should work. At least, it works for me.

String fileName = "árvíztűrőtükörfúrógép.xls";

String userAgent = request.getHeader("user-agent");
boolean isInternetExplorer = (userAgent.indexOf("MSIE") > -1);

try {
    byte[] fileNameBytes = fileName.getBytes((isInternetExplorer) ? ("windows-1250") : ("utf-8"));
    String dispositionFileName = "";
    for (byte b: fileNameBytes) dispositionFileName += (char)(b & 0xff);

    String disposition = "attachment; filename=\"" + dispositionFileName + "\"";
    response.setHeader("Content-disposition", disposition);
} catch(UnsupportedEncodingException ence) {
    // ... handle exception ...
}

Of course, this is tested only on browsers mentioned above and I cannot guarante on 100% that this will work in any browser all time.

Note #1 (@fallen): It's not correct to use URLEncoder.encode() method. Despite method's name, it doesn't encode string into URL-encoding, but it does encode into form-encoding. (Form-encoding is quite similiar to URL-encoding and in a lot of cases it produces same results. But there are some differences. For example space character ' ' is encoded different: '+' instead of '%20')

For correct URL-encoded string you should use URI class:

URI uri = new URI(null, null, "árvíztűrőtükörfúrógép.xls", null);
System.out.println(uri.toASCIIString());

这篇关于Java servlet下载文件名特殊字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆