我们知道,JQuery的ajax函数的返回类型只有xml、text、json、html等类型,没有“流”类型,所以我们要实现ajax下载,不能够使用相应的ajax函数进行文件下载。但在js中 生成一个form,用这个form提交参数,并返回“流”类型的数据。在实现过程中,页面也没有进行刷新。
注意,如果服务器端是Spring MVC,则该server端必须支持 post方法且 content type 是 "application/x-www-form-urlencoded"
下面的例子均已调试通过。
前端JS页面例子:
mp.jsp
manipulationHistory.downloadData = function() {
//定义一个form表单
var myform = $("<form></form>");
myform.attr('method','post')
myform.attr('action',"/manipulationHistory/exportManipulationInfo");
var myProductId = $("<input type='hidden' name='productId' />")
myProductId.attr('value',$("#query-param-product-id").val());
var myPurchaseOrderId = $("<input type='hidden' name='purchaseOrderId' />")
myPurchaseOrderId.attr('value',$("#query-param-dispatched-po").val());
var myWarehouseId = $("<input type='hidden' name='warehouseId' />")
myWarehouseId.attr('value', $("#query-param-warehouse-id").val());
var myRelatedOrderId = $("<input type='hidden' name='relatedOrderId' />")
myRelatedOrderId.attr('value', $("#query-param-order-id").val());
var myUpdateReason = $("<input type='hidden' name='updateReason' />")
myUpdateReason.attr('value', $("#query-param-update-reason").val());
var myStartTime = $("<input type='hidden' name='startTime' />")
myStartTime.attr('value', $("#operate-time-start-value").val());
var myEndTime = $("<input type='hidden' name='endTime' />")
myEndTime.attr('value', $("#operate-time-end-value").val());
myform.append(myProductId);
myform.append(myPurchaseOrderId);
myform.append(myWarehouseId);
myform.append(myRelatedOrderId);
myform.append(myUpdateReason);
myform.append(myStartTime);
myform.append(myEndTime);
myform.appendTo('body').submit(); //must add this line for higher html spec
};
后台server端的java代码如下(用SPring MVC来支持)
/*
* Ajax not support stream response message, so front page need to use form
* to submit request with APPLICATION_FORM_URLENCODED
*/
@Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
@RequestMapping(value = "/exportManipulationInfo", method = RequestMethod.POST)
@ResponseBody
public boolean exportManipulationInfo(HttpServletRequest request, HttpServletResponse response) {
ManipulationInfoQuery manipulationInfoQuery = generateMHQuery(request);
LOG.info("[IMS_INFO][exportManipulationInfo] received request: " + JsonHelper.toJson(manipulationInfoQuery));
List<ManipulationInfo> resultList = manipulationHistoryPageService.getManipulationInfoListWithoutPage(manipulationInfoQuery);
if (null == resultList || resultList.isEmpty()) {
LOG.info(" no data retrieved for query: " + JsonHelper.toJson(manipulationInfoQuery));
}
return downLoadsExcel(resultList, response);
}
private ManipulationInfoQuery generateMHQuery(HttpServletRequest request) {
ManipulationInfoQuery resultQuery = new ManipulationInfoQuery();
resultQuery.setProductId(request.getParameter("productId"));
resultQuery.setPurchaseOrderId(request.getParameter("purchaseOrderId"));
String warehouseID = request.getParameter("warehouseId");
if (StringUtils.isNotBlank(warehouseID)) {
resultQuery.setWarehouseId(Integer.parseInt(warehouseID));
} else {
resultQuery.setWarehouseId(null);
}
resultQuery.setRelatedOrderId(request.getParameter("relatedOrderId"));
resultQuery.setUpdateReason(request.getParameter("updateReason"));
resultQuery.setStartTime(request.getParameter("startTime"));
resultQuery.setEndTime(request.getParameter("endTime"));
resultQuery.setPageInd(null);
resultQuery.setPageSize(null);
return resultQuery;
}
private boolean downLoadsExcel(List<ManipulationInfo> dataList, HttpServletResponse response) {
FileOutputStream fos = null;
try {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("ManipulationInfo_details");
sheet.setDefaultColumnWidth(40);
HSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HSSFCellStyle.ALIGN_LEFT);
String fileName = "ManipulationInfoData-" + String.valueOf(System.currentTimeMillis()).substring(4, 13) + ".xls";
fos = new FileOutputStream(fileName);
// column name
String[] label = { "index", "productId", "productName", "warehouseId", "warehouseName", "dispatchedPo", "relatedOrderId", "updateField", "action",
"result", "updateReason", "operator", "operateTime" };
int columnNum = label.length;
// set title column at line 0
HSSFRow titleRow = sheet.createRow((int) 0);
// the most left column is index of column
HSSFCell titleCell = null;
for (int n = 0; n < columnNum; n++) {
titleCell = titleRow.createCell(n);
titleCell.setCellType(HSSFCell.CELL_TYPE_STRING);
titleCell.setCellValue(label[n]);
titleCell.setCellStyle(style);
}
if (null != dataList && !dataList.isEmpty()) {
for (int rowIndex = 0; rowIndex < dataList.size(); rowIndex++) {
ManipulationInfo item = dataList.get(rowIndex);
/*
* the line 0 is title line,so actual data line begins from
* the next one line.
*/
HSSFRow row = sheet.createRow(rowIndex + 1);
String rowData[] = { item.getProductId(), item.getProductName(), item.getWarehouseId().toString(), item.getWarehouseName(),
item.getDispatchedPo(), item.getRelatedOrderId(), item.getUpdateField(), item.getAction(), item.getResult().toString(),
item.getUpdateReason(), item.getOperator(), item.getOperateTime() };
// create the most left column as index column
HSSFCell cell = row.createCell(0, HSSFCell.CELL_TYPE_NUMERIC);
cell.setCellValue(rowIndex + 1);
cell.setCellStyle(style);
// create the remaining cells at the same line
for (int columnIndex = 1; columnIndex < columnNum; columnIndex++) {
cell = row.createCell(columnIndex, HSSFCell.CELL_TYPE_STRING);
cell.setCellValue(rowData[columnIndex - 1]);
cell.setCellStyle(style);
}
}
} else {
LOG.info(" no data retrieved");
}
// set all columns to automatically adjust column width
for (int i = 0; i < columnNum; i++) {
sheet.autoSizeColumn(i);
}
wb.write(fos); // write workbook into file .xls
fos.flush(); // flush buffer to file
fos.close(); // remember to close it
if (wb != null) {
response.reset();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes(), "iso-8859-1"));
OutputStream out = response.getOutputStream();
wb.write(out);
out.flush();
out.close();
}
} catch (Exception e) {
LOG.error( downLoadsExcel exception:" + e);
return false;
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
LOG.error(" close FileOutputStream error:" + e);
return false;
}
}
}
return true;
}
在上面的JAVA后端代码中,注意没有@RequestBody来修饰传入参数,这是因为如下说明:
关于@ResponseBody,@RequestBody,@PathVariable比较通俗的解释就是:
@PathVariable主要是用来处理URl路径的问题,利用@PathVariable可以是实现在URL路径中实现参数的隐藏效果。
@RequestBody主要是用来处理请求类型转换问题,例如可以把json字符串通过配置自动转换为对象之类的。
@ResponseBody主要是用来处理返回类型转换问题,例如可以把json字符串通过配置自动转换为对象之类的。
一般@ResponseBody,@RequestBody都是用来处理json和xml数据类型,不能用于传统的html解析,因为@ResponseBody,@RequestBody都只是获取内容而已,并不是整个html,所以在有用到json或者xml数据类型传输的时候才可以考虑使用@ResponseBody,@RequestBody这两个注解,否则不要使用。
一个不错的连接是:
http://blog.csdn.net/linzhiqiang0316/article/details/52328153