Java Web工程部署到Tomcat中,下载文件时,中文文件名乱码,JS中和Action都已编码,JS代码如下:
<a href="#" onclick="_download(this.innerHTML)">协同备案表(样表)+项目决算表(样表).docx</a>
function _download(fileName) {
window.location.href = "${request.contextPath}/download/java/" + encodeURIComponent(encodeURIComponent(fileName));
}
Java代码如下:
@RequestMapping("/download/java/{fileName}.{extension}")
public void downloadJava(HttpServletRequest request,
@PathVariable("fileName") String fileName, @PathVariable("extension") String extension, HttpServletResponse response) throws IOException {
if (StringUtils.isEmpty(fileName)) {
throw new IOException("文件名格式非法 [" + fileName + "]");
}
boolean pass = false;
try {
pass = Semaphore.tryAcquire(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
CAT.info(e);
throw new IOException(e);
}
if (pass) {
try {
fileName = URLDecoder.decode(fileName, "UTF-8");
CAT.info("下载文件为:fileName=" + fileName + "." + extension);
String path = request.getServletContext().getRealPath("/");
path += "template/" + fileName + "." + extension;
doDownload(path, response);
} finally {
Semaphore.release();
}
} else {
throw new IOException("当前下载人数过多, 请您稍后再试!");
}
}
private void doDownload(String path, HttpServletResponse response) throws IOException {
//2017-5-16 处理IE直接打开文件及中文文件名乱码的问题
String fileName = path.substring(path.lastIndexOf("/")+1, path.length());
fileName = new String(fileName.getBytes("UTF-8"));
fileName = URLEncoder.encode(fileName, "UTF-8");
fileName = fileName.replaceAll("%28", "(");
fileName = fileName.replaceAll("%29", ")");
fileName = fileName.replaceAll("%2B", "+");
fileName = fileName.replaceAll("%20", " ");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/octet-stream;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment; filename="+fileName);
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(new File(path)));
bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[2048];
int bytesRead = -1;
while ((bytesRead = bis.read(buff, 0, buff.length)) != -1) {
bos.write(buff, 0, bytesRead);
}
} catch (IOException e) {
CAT.error(e);
throw e;
} finally {
try {
if (bis != null)
bis.close();
} catch (IOException e) {
}
try {
if (bos != null)
bos.close();
} catch (IOException e) {
}
}
}
根据以上配置,本地测试没问题,但在服务器中运行时,下载文件名乱码。后来发现在Eclipse中启动Tomcat时,启动日志中有一句”-Dfile.encoding=UTF-8”,启动日志如下:
五月 17, 2017 2:34:04 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Command line argument: -Dcatalina.base=F:\server
五月 17, 2017 2:34:04 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Command line argument: -Dcatalina.home=D:\apache-tomcat-7.0.75
五月 17, 2017 2:34:04 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Command line argument: -Dwtp.deploy=F:\server\webapps
五月 17, 2017 2:34:04 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Command line argument: -Djava.endorsed.dirs=D:\apache-tomcat-7.0.75\endorsed
五月 17, 2017 2:34:04 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Command line argument: -Dfile.encoding=UTF-8
五月 17, 2017 2:34:04 下午 org.apache.catalina.core.AprLifecycleListener lifecycleEvent
信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Program Files\Java\jre7\bin;C:\windows\Sun\Java\bin;C:\windows\system32;C:\windows;C:\apache-maven-3.3.9\bin;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Common Files\Lenovo;C:\ProgramData\Lenovo\ReadyApps;C:\Program Files\TortoiseSVN\bin;C:\Program Files\Java\jdk1.7.0_79\bin;C:\Program Files\Java\jdk1.7.0_79\jre\bin;C:\Program Files (x86)\MySQL\MySQL Server 5.7\bin;C:\Program Files (x86)\MySQL\MySQL Server 5.5\bin;C:\Python27;;.
五月 17, 2017 2:34:04 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler [“http-bio-8080”]
五月 17, 2017 2:34:04 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler [“ajp-bio-8009”]
五月 17, 2017 2:34:04 下午 org.apache.catalina.startup.Catalina load
信息: Initialization processed in 440 ms
由此可知是Tomcat启动参数导致的乱码,修改服务器的Tomcat的启动参数,修改Tomcat的bin目录下的catalina.bat文件,第一行加上“set JAVA_OPTS=-Dfile.encoding=UTF-8”,重启Tomcat,发现下载文件名乱码的问题解决了。