编码问题仅在产品上?
Encoding issue only on prod?
我使用 PlayFramework 2.3 构建了一个应用程序,有时我上传了一个 CSV 文件并用它填充了一个数据库。
在本地(127.0.0.1:9000)访问应用程序并进行上传时,一切正常,文件上传、解析和添加到数据库中没有任何问题。
在生产中执行相同的程序,但所有重音字符都替换为 ��
。
dev 和 prod 之间的主要区别是:
- 在 DEV 中,我直接从 PlayFramework (localserver) 访问应用程序
- 在 PROD 中,我通过 NGinx 访问应用程序,重定向到 Play(代理)的本地实例。
详细信息如下:
- CSV文件是UTF-8编码的(注:当然是我测试的同一个文件)
- 使用 UTF-8 连接到数据库 ->
db.default.url="jdbc:mysql://127.0.0.1/2leadin?characterEncoding=UTF-8"
- 我测试过(使用 Firefox),HTML 页面以 UTF-8
返回
最后,这是我的 NGinx 配置:
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme "https";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
server {
listen 80;
server_name my.2lead.in;
return 301 https://my.2lead.in;
}
server {
listen 443;
ssl on;
root /var/www/2lead.in/errors/;
# http://www.selfsignedcertificate.com/ is useful for development testing
ssl_certificate /ssl/2lead.crt;
ssl_certificate_key /ssl/2lead.key;
# From https://bettercrypto.org/static/applied-crypto-hardening.pdf
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # not possible to do exclusive
ssl_ciphers 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA';
add_header Strict-Transport-Security max-age=15768000; # six months
# use this only if all subdomains support HTTPS!
# add_header Strict-Transport-Security "max-age=15768000; includeSubDomains"
keepalive_timeout 70;
server_name my.2lead.in;
# remove the robots line if you want to use wordpress' virtual robots.txt
location = /robots.txt { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
location /public {
alias /var/www/2lead.in/my/public/;
access_log off;
log_not_found off;
}
location / {
proxy_pass http://127.0.0.1:9100;
}
location ~ /\.git {
deny all;
}
error_page 502 @maintenance;
location @maintenance {
rewrite ^(.*)$ /error502.html break;
}
}
我遗漏了什么,你知道为什么我只在 PROD 中遇到编码问题吗?我很确定这是因为 NGinx,但我找不到原因。
谢谢。
默认的 Java 字符集依赖于语言环境,取自 file.encoding
环境变量(参见 this answer)。正如您所看到的,这可能会导致不同机器上的行为差异。两种修复方法,权宜之计和更健壮便携的方法:
- 确保您的服务器是 运行
-Dfile.encoding=UTF-8
(或任何与您的开发环境匹配的服务器)
- 确保所有文件操作都明确指定字符集,如this answer所述
总而言之,依赖默认的系统编码是脆弱的,在大多数情况下应该避免。
我使用 PlayFramework 2.3 构建了一个应用程序,有时我上传了一个 CSV 文件并用它填充了一个数据库。
在本地(127.0.0.1:9000)访问应用程序并进行上传时,一切正常,文件上传、解析和添加到数据库中没有任何问题。
在生产中执行相同的程序,但所有重音字符都替换为 ��
。
dev 和 prod 之间的主要区别是:
- 在 DEV 中,我直接从 PlayFramework (localserver) 访问应用程序
- 在 PROD 中,我通过 NGinx 访问应用程序,重定向到 Play(代理)的本地实例。
详细信息如下:
- CSV文件是UTF-8编码的(注:当然是我测试的同一个文件)
- 使用 UTF-8 连接到数据库 ->
db.default.url="jdbc:mysql://127.0.0.1/2leadin?characterEncoding=UTF-8"
- 我测试过(使用 Firefox),HTML 页面以 UTF-8 返回
最后,这是我的 NGinx 配置:
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme "https";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
server {
listen 80;
server_name my.2lead.in;
return 301 https://my.2lead.in;
}
server {
listen 443;
ssl on;
root /var/www/2lead.in/errors/;
# http://www.selfsignedcertificate.com/ is useful for development testing
ssl_certificate /ssl/2lead.crt;
ssl_certificate_key /ssl/2lead.key;
# From https://bettercrypto.org/static/applied-crypto-hardening.pdf
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # not possible to do exclusive
ssl_ciphers 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA';
add_header Strict-Transport-Security max-age=15768000; # six months
# use this only if all subdomains support HTTPS!
# add_header Strict-Transport-Security "max-age=15768000; includeSubDomains"
keepalive_timeout 70;
server_name my.2lead.in;
# remove the robots line if you want to use wordpress' virtual robots.txt
location = /robots.txt { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
location /public {
alias /var/www/2lead.in/my/public/;
access_log off;
log_not_found off;
}
location / {
proxy_pass http://127.0.0.1:9100;
}
location ~ /\.git {
deny all;
}
error_page 502 @maintenance;
location @maintenance {
rewrite ^(.*)$ /error502.html break;
}
}
我遗漏了什么,你知道为什么我只在 PROD 中遇到编码问题吗?我很确定这是因为 NGinx,但我找不到原因。
谢谢。
默认的 Java 字符集依赖于语言环境,取自 file.encoding
环境变量(参见 this answer)。正如您所看到的,这可能会导致不同机器上的行为差异。两种修复方法,权宜之计和更健壮便携的方法:
- 确保您的服务器是 运行
-Dfile.encoding=UTF-8
(或任何与您的开发环境匹配的服务器) - 确保所有文件操作都明确指定字符集,如this answer所述
总而言之,依赖默认的系统编码是脆弱的,在大多数情况下应该避免。