首先说明下各浏览器对文件下载的文件名解析编码如下:
1. IE浏览器,采用URLEncoder编码
2. Opera浏览器,采用filename*方式
3. Safari浏览器,采用ISO编码的中文输出
4. Chrome浏览器,采用Base64编码或ISO编码的中文输出
5. FireFox浏览器,采用Base64或filename*或ISO编码的中文输出
那么IE浏览器的文件名编码解析就得单独处理了。
Sturts2的下载处理方法如下:
package com.dhcc.iscp.web.filedownload.action;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Date;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.InterceptorRefs;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.springframework.context.annotation.Scope;
import com.dhcc.framework.exception.DataBaseException;
import com.dhcc.framework.util.StringUtils;
import com.dhcc.iscp.service.exchangestandard.BusinessOrganDictionaryInfoService;
import com.dhcc.iscp.service.exchangestandard.OrganTermRangeInfoService;
import com.dhcc.iscp.util.DateUtil;
import com.opensymphony.xwork2.ActionSupport;
@Namespace(value = "/download")
@Scope("prototype")
@Action("MappingDownloadCtrl")
@Results({
@Result(name = "success", type = "stream", params = { "contentType", "application/vnd.ms-excel;charset=UTF-8",
// 两个是一对属性设置
"inputName", "excelStream", "contentDisposition", "attachment;filename=\"${fileName}.xls\"" }) })
@InterceptorRefs({@InterceptorRef("fileUpload"),@InterceptorRef("dhccStack")})
public class MappingDownloadAction extends ActionSupport {
private static final long serialVersionUID = -8499404699578479452L;
private InputStream excelStream;
// 文件名称
private String fileName;
/**
* @return fileName
*/
public String getFileName() {
return fileName;
}
/**
* @param fileName
* fileName
*/
public void setFileName(String fileName) {
this.fileName = fileName;
}
public InputStream getExcelStream() {
return excelStream;
}
@Resource
OrganTermRangeInfoService organTermRangeInfoService;
@Resource
BusinessOrganDictionaryInfoService organDicInfoService;
private void templateDownload(String fileName) {
HttpServletRequest request = ServletActionContext.getRequest();
try {
InputStream inputStream = MappingDownloadAction.class.getClassLoader()
.getResourceAsStream("/download/" + fileName + ".xls");
HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
this.workbook2InputStream(workbook,fileName,request);
} catch (Exception e) {
throw new DataBaseException(e.getMessage(), e);
}
}
private void workbook2InputStream(HSSFWorkbook workbook, String fileName,HttpServletRequest request) throws Exception {
//如果是IE浏览器,则用URLEncode解析
if(isMSBrowser(request)){
fileName = URLEncoder.encode(fileName, "UTF-8");
}else{//如果是谷歌、火狐则解析为ISO-8859-1
fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
}
this.fileName = fileName; // 设置fileName
ByteArrayOutputStream baos = new ByteArrayOutputStream();
workbook.write(baos);
baos.flush();
byte[] aa = baos.toByteArray();
excelStream = new ByteArrayInputStream(aa, 0, aa.length);
baos.close();
}
//方法功能描述: 判断是否是IE浏览器
public boolean isMSBrowser(HttpServletRequest request) {
String[] IEBrowserSignals = {"MSIE", "Trident", "Edge"};
String userAgent = request.getHeader("User-Agent");
for (String signal : IEBrowserSignals) {
if (userAgent.contains(signal)){
return true;
}
}
return false;
}
}
注意:对文件名的解析请在统一位置处理,避免反复编码解析而导致的中文乱码。
经测试该方法对IE8可行,谷歌火狐也没无异常。