场景描述
本地windows系统使用谷歌浏览器批量导出300个word文件的zip压缩包,解压时里面300个文件的中文名称未乱码;当客户那边使用麒麟桌面linux操作系统使用浏览器导出zip压缩包时,里面的中文文件名乱码了;
解决过程
处理思路3步走:①获取客户浏览器的系统,后续分开处理;②使用apache下的压缩流设置编码时,对linux和windows系统进行编码集处理;③压缩流对将要处理的文件设置Unix权限;
使用poi-tl、UserAgentUtils、apache下的压缩包流 处理该问题,maven地址如下
<!--解析userAgent-->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
<version>1.20</version>
</dependency>
<!-- poi-tl,官方文档:http://deepoove.com/poi-tl/ -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.10.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.ant/ant -->
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.0</version>
</dependency>
// 使用poi-tl、UserAgentUtils、apache下的压缩包流 处理该问题
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.deepoove.poi.util.PoitlIOUtils;
import eu.bitwalker.useragentutils.UserAgent;
public void exportWordToZip(HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpSession session= request.getSession();
String[] ids = getWordIds();
String[] wordNames = getWordNames();
session.removeAttribute("exportEmpResume2SessionIds");
session.removeAttribute("exportEmpResume2SessionWordNames");
// userAgent中有很多获取请求信息的方法
UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
// 获取客户端请求的浏览器类型
String browserName = userAgent.getBrowser().toString();
System.out.println("用户浏览器名称:"+browserName);
String osName = userAgent.getOperatingSystem().getName();
System.out.println("用户操作系统名称:"+osName);
boolean mutilWordNameFlag = false;//定义一个批量导出的文件是否转码标识
if(osName.indexOf("Windows")>=0){
mutilWordNameFlag = false;
}else if(osName.indexOf("Linux")>=0){
mutilWordNameFlag = true;
}else{
throw new RuntimeException("暂时不支持 "+osName+" 操作系统");
}
String templateFile = "word.docx";//人员信息卡片模板
String templatePath = request.getSession().getServletContext().getRealPath("/")+"template"+File.separatorChar+templateFile;
String picFolderPath =request.getSession().getServletContext().getRealPath("/") + "upload"+ File.separatorChar+"customform_grid";//获取图片所在文件夹
if(wordNames.length==ids.length && ids.length>0){
List<String> wordNameList = new ArrayList<>();
for (int i = 0; i < wordNames.length; i++) {
wordNameList.add(wordNames[i]);
}
//获取word所需的map格式数据
List<Map<String,Object>> maps = new ArrayList<>();
maps = getWordMapDatas(ids,wordNames,picFolderPath);
String zipName = "001测试压缩包.zip";
response.reset();
response.setContentType("application/x-msdownload");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + new String(zipName.getBytes("gbk"), "iso8859-1"));
File file = null;
InputStream fin = null;
ZipOutputStream zos = null;
FileInputStream in = null;
OutputStream out = response.getOutputStream();
List<String> pathList = new ArrayList<>();
try {
zos = new ZipOutputStream(out);
if(mutilWordNameFlag){
//如果是linux桌面系统设置一下编码
zos.setEncoding("utf-8");
}else{
//mutilWordNameFlag不是系统的判断,是浏览器的判断,这里直接设置压缩包为gbk编码
zos.setEncoding("gbk");
}
for (int i = 0; i < maps.size(); i++) {
String wordName = wordNameList.get(i);
String path = request.getSession().getServletContext().getRealPath(wordName);
pathList.add(path);
LoopRowTableRenderPolicy hackLoopTableRenderPolicy = new LoopRowTableRenderPolicy();
Configure config = Configure.builder().bind("efList", hackLoopTableRenderPolicy).build();//遍历家庭成员信息
XWPFTemplate template = XWPFTemplate.compile(templatePath, config).render(maps.get(i));
template.writeToFile(path);
file = new File(path);
// 对其设置Unix权限
ZipEntry zipEntry = new ZipEntry(wordName);
zipEntry.setUnixMode(644);
zos.putNextEntry(zipEntry);
byte[] buf = new byte[2 * 1024];
int len;
in = new FileInputStream(file);
while ((len = in.read(buf)) != -1) {
zos.write(buf, 0, len);
}
zos.closeEntry();
in.close();
}
zos.close();
out.flush();
out.close();
} finally {
if(fin != null) {
fin.close();
}
if(zos != null) {
zos.close();
}
if(!pathList.isEmpty()){
for (int i = 0; i < pathList.size(); i++) {
File file1 = new File(pathList.get(i));
if(file1.exists()){
file1.delete();
}
}
}
}
}
}