0%

服务器生成中文文件失败的问题解决

背景

一个项目中的一个功能是根据数据生成一份PDF文档,并下载到用户本地。在开发环境下一切正常。在测试环境下发现该功能如果需要的生成的文件名称包括非ASCII字符(比如中文、全角标点),文件无法下载。

问题排查

第三方库

生成PDF文件采用了第三方库,首先想到是它的兼容问题。但又马上排除,因为生产环境是一套代码,并未出现类似问题。

tomcat

之前解决过中文文件名称下载后显示名称乱码的问题。这里的设置也做了:

1
<Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

设置过后问题仍然存在,没有生成相应的问题。

测试机环境

测试机是linux(CentOS 6.9 ),检查其语言设置,执行:

1
locale

得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
LANG=C.UTF-8
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=C

补充了一下相关知识,这里可以简单理解C对应的是ASCII字符环境。

做一下修改,执行:

1
vim /etc/profile

进入vim界面编辑内容,发现其中设置:

1
export LC_ALL=C

修改为:

1
export LC_ALL=zh_CN.UTF-8

保存退出。

让修改生效:

1
source /etc/profile

再次执行locale,得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
LANG=C.UTF-8
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=zh_CN.UTF-8

重启了一次tomcat后,问题解决了。中文文件名没问题,顺手测试了一个日文字符也没问题。

新知识总结

服务器的locale设置影响写文件,采用UTF-8字符集设置语言,兼容性要强于默认的设置(ASCII字符集)。

设置中:LC_ALL的优先级最高,它们之间有一个优先级的关系:LC_ALL > LC_* > LANG。(这点没验证)。

参考资料

linux系统字符编码详解

Locale

Locale的概念及setlocale函数