在使用 renderFile 进行下载操作的时候,发现文件名是乱码的,文件的内容是ok的,查看了一下源码,发现是 FileRender 里强制转换成了 GBK,但是我的文件名是存在编码为 UTF-8 的数据库里的,个人猜想是这个原因导致乱码的,但是源码的设计使得很难扩展,求思路。
其实这个将 GBK 转成 ISO8859-1 就是为了支持中文名的,测试是可以支持utf-8也可以支持,出现这个问题原因暂时不明,建议自建一个 MyFileRender 然后覆盖 render 方法,将这个地方改一下,用的时候这么用: render(new MyFileRender(...)),解决问麻烦过来反馈一下,另外解决中文问题后要再试试英文文件名,目前 jfinal 的做法就是为了支持中英文
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
自己重写了一个 render 结果就ok了。代码如下:
public class MyFileRender extends Render {
private static final String DEFAULT_FILE_CONTENT_TYPE = "application/octet-stream";
private File file;
private ServletContext servletContext;
public MyFileRender(String fileName) {
if(StrKit.isBlank(fileName)) {
throw new IllegalArgumentException("fileName can not be blank.");
} else {
fileName = fileName.trim();
String fullFileName;
String baseDownloadPath = InternShipManagementConfig.FILE_HOST;
if(!fileName.startsWith("/") && !fileName.startsWith("\\")) {
fullFileName = baseDownloadPath + File.separator + fileName;
} else if(baseDownloadPath.equals("/")) {
fullFileName = fileName;
} else {
fullFileName = baseDownloadPath + fileName;
}
this.file = new File(fullFileName);
}
this.servletContext = JFinal.me().getServletContext();
}
public MyFileRender(File file) {
this.file = file;
this.servletContext = JFinal.me().getServletContext();
}
@Override
public void render() {
if (file == null || !file.isFile() || file.length() > Integer.MAX_VALUE) {
RenderFactory.me().getErrorRender(404).setContext(request, response).render();
return ;
}
//源码中的代码
//response.addHeader("Content-disposition", "attachment; filename=" + file.getName());
//修改后的代码 解决中文乱码问题
try {
response.addHeader("Content-disposition",
"attachment; filename=" + new String(file.getName().getBytes("utf-8"), "ISO8859-1"));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
String contentType = servletContext.getMimeType(file.getName());
if (contentType == null) {
contentType = DEFAULT_FILE_CONTENT_TYPE; // "application/octet-stream";
}
response.setContentType(contentType);
response.setContentLength((int)file.length());
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
outputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
for (int n = -1; (n = inputStream.read(buffer)) != -1;) {
outputStream.write(buffer, 0, n);
}
outputStream.flush();
}
catch (Exception e) {
throw new RenderException(e);
}
finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
这是我在网上找到的重写 render 的代码,其中我就只是修改了 encoding,new String(file.getName().getBytes("utf-8"), "ISO8859-1"))
就改了这句,把 UTF8 转为 ISO8859-1。(其中的 baseDownloadPath 不知道在 constants.setBaseDownloadPath 后怎么去 get
出来,所以这里用了自己定义的一个全局变量,顺便请教一下)
我觉得是不是可以提供一个设置 encoding 的方法呢?感觉这样会更加方便开发者想要去定制
@MadisonRong 麻烦测试一下这种解决方案下中文文件名是否支持? jfinal 当前的实现本质上是为了支持中文
他说这种方案能解决中文文件名,他的文件名是从数据库拿出来的,数据库是使用UTF-8编码,所以用GBK获取文件名会乱码。 而jfinal源码可能是直接读取系统的文件名,所以用了GBK,这是我的猜测
@JFinal 楼上表达了我的意思了,我的文件名的那个字符串是从一个编码为 UTF-8 的数据库里读取出来的,我也猜想可能是这个原因导致我在用 jFinal 的 renderFile 的时候中文文件名会乱码。经过测试,我这样做法,中英文都ok。
@MadisonRong 这里已做出改进,encodeFileName() 方法已改为 protected方便继承扩展,并且代码改为了:return new String(fileName.getBytes(getEncoding()), "ISO8859-1");使用系统设置的encoding,应该可以了,下一版本会更新这里,感谢反馈。
@MadisonRong @whyyy 现在可以通过升级到 jfinal 2.2 来解决问题了:http://www.oschina.net/news/70001/jfinal-2-2
状态更改为 已关闭
@JFinal 嗯,收到微信的推送了,有看到更新
登录 后才可以发表评论