Java servlet下载文件名特殊字符

jab*_*bal 10 java encoding servlets download

我正在编写一个简单的文件下载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"; //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();
  }
Run Code Online (Sandbox Code Playgroud)

spo*_*rak 20

我发现解决方案适用于我安装的所有浏览器(IE8,FF16,Opera12,Chrome22).
它基于以下事实:如果没有指定[不同]编码,浏览器期望文件名参数中的值,即在浏览器本机编码中编码.

通常浏览器的本机编码是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);

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 ...
}
Run Code Online (Sandbox Code Playgroud)

当然,这仅在上面提到的浏览器上进行测试,我无法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());
Run Code Online (Sandbox Code Playgroud)

  • IE的原生编码是中/东欧代码页吗?你一定是在开玩笑.它唯一显示的是IE使用本地浏览器的系统区域设置.遗憾的是,我认为没有一种可靠的方法可以从服务器中检测到它. (3认同)