近期项目中用到了extjs的上传控件上传文件,而后页面使用a标签直接调用后台action获取流进行下载。在本地tomcat下是没有什么问题的,可是当放到测试环境jboss下的时候却遇到了文件名乱码的问题。如下为关键代码:javascript
<!-- 附件下载 --> <action name="downloadFile" class="com.deppon.cc.module.kminfo.server.action.KmInfoAction" method="downloadFile"> <result name="success" type="stream"> <param name="contentType">application/octet-stream</param> <param name="inputName">fileStream</param> <param name="contentDisposition"> attachment;filename="${fileUpdateFileName}" </param> </result> </action>
public InputStream getInputStream(String id){ if ("".equals(id) || id == null) { log.warn("id is null"); throw new FileStorageException(FileStorageException.COMMON_FILE_IDISBLANK); } FileEntity res = fileStorageDao.get(id); if(res == null) { log.warn("get file is null"); throw new FileStorageException(FileStorageException.COMMON_FILE_GETFILEISBLANK); } byte[] sfile = res.getSerializedFile(); //根据ID获取文件 InputStream fis = new ByteArrayInputStream(sfile); return fis; }
/*页面中用<a>标签进行下载*/ var url = "../kminfo/downloadFile.action?kmInfoVO.fileUpdateId=" + annex + "&&kmInfoVO.fileUpdateFileName=" + annexName; var uploadAttachmentForm = infoEditWindow.down('form').down('form').getForm().findField('fileUpdateNameDisp').setValue("<a href ='"+ url +"'>"+annexName+"</a>");
当点击a标签以后,文件名称和文件id会被传到后台,后台根据文件id去查找文件,而后放入流中,struts2中的配置了下载的文件名,它会去调用getFileUpdateFileName()方法去取的文件名,而后再返回到前台。
由于是经过a标签传的中文,在到达后台的时候已经被解码成了不知道什么编码,试着在后台get方法中对文件进行转换:java
new String(fileUpdateFileName.getBytes("UTF-8"),"ISO-8859-1");
本地可行,可是jboss下仍是乱码。试了不少的方法都没办法解决这个问题,最后决定在前台就对中文名进行转码,而后到后台去解码。浏览器
/*页面中用<a>标签进行下载*/ var url = "../kminfo/downloadFile.action?kmInfoVO.fileUpdateId=" + annex + "&&kmInfoVO.fileUpdateFileName=" + encodeURI(encodeURI(annexName)); var uploadAttachmentForm = infoEditWindow.down('form').down('form').getForm().findField('fileUpdateNameDisp').setValue("<a href ='"+ url +"'>"+annexName+"</a>");
这里必需要encodeURI两次,若是是一次的话浏览器仍是会把他解析为中文,那么也就无效了。tomcat
public String downloadFile(){ try { getKmInfoVO().setFileUpdateFileName(new String(URLDecoder.decode(getKmInfoVO().getFileUpdateFileName(),"UTF-8").getBytes("UTF-8"), "ISO-8859-1")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } InputStream fileStream = fileStorageService.getInputStream(getKmInfoVO().getFileUpdateId()); kmInfoVO.setFileStream(fileStream); return SUCCESS; }
后台只须要URLDecoder一次就能够成功解码了,最后通过在本地和测试环境上均可行。最后再说一下,不少状况下,咱们在写程序的时候都会把代码设置为UTF-8的编码,能够在下载文件设置filename的时候却要设置编码格式为ISO-8859-1(如是英文的话就不须要这样处理了)。
先说为何使用 ISO-8859-1 编码,这个主要是因为http协议,http header头要求其内容必须为iso-8859-1编码,因此咱们最终要把其编码为 ISO-8859-1 编码的字符串;
可是前面为何不直接使用 "中文文件名".getBytes("ISO-8859-1"); 这样的代码呢?由于ISO-8859-1编码的编码表中,根本就没有包含汉字字符,固然也就没法经过"中文文件名".getBytes("ISO-8859-1");来获得正确的“中文文件名”在ISO-8859-1中的编码值了,因此再经过new String()来还原就无从谈起了。 因此先经过 "中文文件名".getBytes("utf-8") 获取其 byte[] 字节,让其按照字节来编码,即在使用 new String("中文文件名".getBytes("utf-8"), "ISO-8859-1") 将其从新组成一个字符串,传送给浏览器。app