AJAX文件下载
JQuery的ajax函数的返回类型只有xml、text、json、html等类型,没有“流”类型,所以我们要实现ajax下载,不能够使用相应的ajax函数进行文件下载。但可以用js生成一个form,用这个form提交参数,并返回“流”类型的数据。在实现过程中,页面也没有进行刷新。
注意此示例采用STRUTS2实现,没有采用Struts2内置的文件下载方法。
JS代码如下:
<script type="text/javascript">
function aClick () {
$.ajax({
type : "POST",//提交方式
url : "${pageContext.request.contextPath}/ajaxTest.action",//路径
data : {
id: 1,name:"testtt"
},//数据,这里使用的是Json格式进行传输
success : function(result) {//返回数据根据结果进行相应的处理
var form=$("<form>");//定义一个form表单
form.attr("style","display:none");
form.attr("target","");
form.attr("method","post");
form.attr("action","downloadTest.action");
var input1=$("<input>");
input1.attr("type","hidden");
input1.attr("name","exportData");
input1.attr("value",(new Date()).getMilliseconds());
$("body").append(form);//将表单放置在web中
form.append(input1);
form.submit();//表单提交
}
});
}
</script>
下图有两个超链接,第一个是通过AJAX调用下载ACTION的,第二个直接就是超链接调用ACTION 。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src='full/jquery.min.js'></script>
<title>Insert title here</title>
<script type="text/javascript">
function aClick () {
$.ajax({
type : "POST","ajaxTest.action");
var input1=$("<input>");
input1.attr("type",(new Date()).getMilliseconds());
$("body").append(form);//将表单放置在web中
form.append(input1);
form.submit();//表单提交
}
});
}
</script>
</head>
<body>
<br />
<h2>点击下载</h2>
<a href="javascript:void(0)" onclick="aClick()">文件下载</a>
<a href="ajaxTest.action?fileName=FCN301-Ver.1.1費用申請書.xls">文件下载(超链接)</a>
</body>
</html>
ACTION类如下:(此ACTION类中也有一个下载的方法,都是共通的)
/**
* com.ppl.action.excelDol.java
* @author 作者 : pplsunny
* @version 创建时间:2017年4月8日 下午8:26:39
* 类说明
*/
package com.ppl.action;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.ppl.test.WorkbookDemo;
/**
* XXXX
*/
public class excelDol extends ActionSupport {
public String execute() throws Exception {
String filePath="G:/POI_JAVA/FCN301-Ver.1.1費用申請書.xls";
//下载到客户端
HttpServletResponse response = ServletActionContext.getResponse();
//download(filePath,response);
WorkbookDemo.readTempleteExcel(filePath,response);
//1 获取表单数据
HttpServletRequest request = ServletActionContext.getRequest();
String id = request.getParameter("id");
String name = request.getParameter("name");
System.out.println(id+"--"+name);
return NONE;
}
private void download(String path,HttpServletResponse response) {
try {
// path是指欲下载的文件的路径。
File file = new File(path);
// 取得文件名。
String filename = file.getName();
String strName = new String(filename.getBytes("UTF-8"),"ISO-8859-1");
// 以流的形式下载文件。
InputStream fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header
response.addHeader("Content-Disposition","attachment;filename="
+ new String(filename.getBytes("UTF-8"),"ISO-8859-1"));
response.addHeader("Content-Length","" + file.length());
OutputStream toClient = new BufferedOutputStream(
response.getOutputStream());
response.setContentType("application/vnd.ms-excel;charset=gb2312");
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
EXCEL文件操作类
package com.ppl.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.WorkbookUtil;
public class WorkbookDemo {
/**
* 创建工作簿
* @throws IOException
*/
public static void createWorkBook() throws IOException {
/**
* 工作薄: WorkBook是操作Excel的入口,Excel的文档对象,HSSFWorkbook(2003版本 ),XSSFWorkbook(2007版本)实现了该接口。
* HSSF对应xls格式,XSSF对应xlsx格式
* ------------------------------------------------------------------
* Workbook wb = new XSSFWorkbook();
* FileOutputStream fileOut = new FileOutputStream("workbook.xlsx");
* wb.write(fileOut);
* fileOut.close();
* ------------------------------------------------------------------
*/
final Workbook HSSFwb = new HSSFWorkbook();
/**
* Sheet是在org.apache.poi.ss.usermodel包的接口,它是创建具有特定名称的高或低级别的电子表格的所有类的超接口。
* 页:Sheet表示工作薄的分页。HSSFSheet, XSSFChartSheet,XSSFDialogsheet,XSSFSheet实现了该接口。
* 索引以0开始,以workbook.getNumberOfSheets()-1结束
*/
final String safeName = WorkbookUtil.createSafeSheetName("first sheet");
final Sheet sheet = HSSFwb.createSheet(safeName);
//sheet.autoSizeColumn(6,true);
/**
* 获取工作簿数量
*/
final int sheetCount = HSSFwb.getNumberOfSheets();
System.out.println("sheetCount: " + sheetCount);
/**
* Row:表示页中的一行。HSSFRow,XSSFRow实现了该接口。
* Row的索引以0开始(getFirstRowNum),以getLastRowNum结束
*/
final Row row = sheet.createRow((short) 0);
/**
* 得到的是最后一个不为空的行索引,真实行号是【getLastRowNum()+1】
*/
final int rowNumReal = sheet.getLastRowNum();
/**
* Cell:行中的一个单元格。HSSFCell,XSSFCell实现了该接口。
* Cell的索引以0开始(getFirstCellNum),以getLastCellNum结束,*/
final Cell cell = row.createCell(0);
/**
* 获取当前行中不为空的单元格数
*/
final int cellNumReal = row.getPhysicalNumberOfCells();
/**
* 空单元格返回对应的单元格类型
*/
Cell cell2 = row.getCell(3,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
cell2 = row.getCell(4,Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
cell2 = row.getCell(5,Row.MissingCellPolicy.RETURN_NULL_AND_BLANK);
//设置单元格的数据
cell.setCellValue(1);
// Or do it on one line.
row.createCell(1).setCellValue(1.2);
row.createCell(2).setCellValue("This is a string 速度反馈链接");
row.createCell(3).setCellValue(true);
//----------------------单元格赋值示例START------------------------------------------
/**
* 创建第十行
*/
final Row rowTEN = sheet.createRow((short) 9);
// 填充日期类型的数据---未设置Cell Style
rowTEN.createCell(1).setCellValue(new Date());
// 另一种创建日期的方法
rowTEN.createCell(2).setCellValue(Calendar.getInstance());
/**
* 在第十行的单元格上创建单元格
*/
final Cell cellOther = rowTEN.createCell(5);
cellOther.setCellValue(new Date());
/**
* 获取HSSF的辅助类
*/
final CreationHelper createHelper = HSSFwb.getCreationHelper();
final CellStyle cellStyle = HSSFwb.createCellStyle();
// 填充日期类型的数据---已设置Cell Style
final String timeFormat = "yyyy-MM-dd hh:mm:ss";
cellStyle.setDataFormat(createHelper.createDataFormat().getFormat(timeFormat));
final Cell cell7 = rowTEN.createCell(6);
cell7.setCellValue(new Date());
cell7.setCellStyle(cellStyle);
/**
* 设置单元格宽度自适应,对中文支持不好
*/
sheet.autoSizeColumn((short) 6);
//----------------------单元格赋值示例END------------------------------------------
/**
* 创建一个文件 命名为workbook.xls,默认创建到当前工程的根目录下
*/
final FileOutputStream fileOut = new FileOutputStream("workbook2.xls");
/**
* 把上面创建的工作簿输出到文件中
*/
HSSFwb.write(fileOut);
/**
* 关闭输出流
*/
fileOut.close();
HSSFwb.close();
}
/**
* 使用POI读入excel工作簿文件
* @throws Exception
*/
public static void readWorkBook() throws Exception {
/**
* 从文件流读取Excel
*/
final InputStream inp = new FileInputStream("workbook1.xls");
/**
* 根据上述创建的输入流 创建工作簿对象
*/
final Workbook wb = WorkbookFactory.create(inp);
/**
* 页Sheet是从0开始索引的
*/
final Sheet sheet = wb.getSheetAt(0);
/**
* 按名引用excel工作表
* Sheet sheetByName = wb.getSheet("NAME");
*/
/**
* 获取工作簿的行数
*/
final int rowNumReal = sheet.getLastRowNum();
System.out.println("----------------------");
System.out.println("rowNumReal-->" + rowNumReal);
System.out.println("----------------------");
final int cellNumReal = sheet.getRow(rowNumReal).getPhysicalNumberOfCells();
System.out.println("cellNumReal-->" + cellNumReal);
//利用foreach循环 遍历sheet中的所有行
int rowNum=0;
/**
* 直接采用这种循环空行和空列是不会读取的,
* 即当行有空行或者一行中有空单元格是,循环会跳过去
*/
for (final Row row : sheet) {
rowNum++;
//遍历row中的所有方格
for (final Cell cell : row) {
final String valueT = getCellContentAsString(cell);
System.out.println(cell.toString() + " ---> " + valueT);
}
//每一个行输出之后换行
System.out.println();
}
System.out.println("----------------------");
loopRowAndCell(sheet);
System.out.println("rowNum-->"+rowNum);
//关闭输入流
inp.close();
}
/**
* 遍历一个工作簿中的行和列
* 不包含空行和空列(无需对空行和空列做处理)
* @param sheet
* @throws Exception
*/
public static void loopRealRowAndCell(final Sheet sheet) throws Exception {
/**
* 遍历行
*/
int rowno = 0;
for (final Iterator itemRow = sheet.rowIterator(); itemRow.hasNext();) {
final Row row = (Row) itemRow.next();
rowno++;
System.out.println("----------rowno----------" + rowno);
/**
* 遍历列
*/
for (final Iterator itemCell = row.cellIterator(); itemCell.hasNext();) {
final Cell cell = (Cell) itemCell.next();
/**
* 获取单元格格式类型
* POI 3.15 beta 3. Use CellType.ERROR instead.
*/
String cellValue = "";
switch (cell.getCellTypeEnum()) {
case STRING:// 字符串
cellValue = cell.getRichStringCellValue().getString().trim();
break;
case NUMERIC:// 数字
//如果为时间格式的内容
if (HSSFDateUtil.isCellDateFormatted(cell)) {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
cellValue = sdf.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue())).toString();
break;
} else {
/**
* 解决科学计数法的问题
*/
final Double d = cell.getNumericCellValue();
final DecimalFormat dformat = new DecimalFormat("#.##");
cellValue = dformat.format(d);
}
break;
case BOOLEAN:// Boolean
cellValue = String.valueOf(cell.getBooleanCellValue()).trim();
break;
case FORMULA:// 公式
/**
* 解决公式的取值问题
*/
try {
/**
* 公式计算结果是纯数字
*/
cellValue = String.valueOf(cell.getNumericCellValue());
} catch (final IllegalStateException e) {
/**
* 公式计算结果是不是纯数字
*/
cellValue = String.valueOf(cell.getRichStringCellValue());
}
/**
* 这句获取的是计算公式
*/
//cellValue = cell.getCellFormula() + "";
break;
case BLANK: // 空值
cellValue = "BLANG";
break;
case ERROR: // 故障
cellValue = "N/A";
break;
default://未知类型
cellValue = "ERROR";
}
System.out.println(" cellValue---> " + cellValue);
}
}
}
/**
* 遍历一个工作簿中的行和列
* 包含空行和空列(传统遍历,需要对空行和空列进行处理)
* @param sheet
* @throws Exception
*/
public static void loopRowAndCell(final Sheet sheet) throws Exception {
/**
* 得到的是最后一个不为空的行索引,真实行号是【getLastRowNum()+1】
*/
final int rowNumReal = sheet.getLastRowNum();
/**
* 遍历行
*/
for (int rowIndex = 0; rowIndex <= rowNumReal; rowIndex++) {
/**
* 获取当前行
*/
final Row row = sheet.getRow(rowIndex);
/**
* 空行处理
*/
if (null == row) {
System.out.println(" BLANG ROW " + rowIndex);
continue;
}
/**
* 取得当前行的列数
*/
final int cellCount = row.getLastCellNum();
/**
* 遍历列
*/
for (int cellIndex = 0; cellIndex < cellCount; cellIndex++) {
/**
* 获取当前列,如果当前列不存在(为空)则返回一个单元格类型为空的单元格
*/
final Cell cell = row.getCell(cellIndex,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
/**
* 空列处理
*/
if (null == cell) {
System.out.println(" BLANG CELL " + cellIndex);
continue;
}
/**
* 获取单元格格式类型
* POI 3.15 beta 3. Use CellType.ERROR instead.
*/
String cellValue = "";
switch (cell.getCellTypeEnum()) {
case STRING:// 字符串
cellValue = cell.getRichStringCellValue().getString().trim();
break;
case NUMERIC:// 数字
//如果为时间格式的内容
if (HSSFDateUtil.isCellDateFormatted(cell)) {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
cellValue = sdf.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue())).toString();
break;
} else {
/**
* 解决科学计数法的问题
*/
final Double d = cell.getNumericCellValue();
final DecimalFormat dformat = new DecimalFormat("#.##");
cellValue = dformat.format(d);
}
break;
case BOOLEAN:// Boolean
cellValue = String.valueOf(cell.getBooleanCellValue()).trim();
break;
case FORMULA:// 公式
/**
* 解决公式的取值问题
*/
try {
/**
* 公式计算结果是纯数字
*/
cellValue = String.valueOf(cell.getNumericCellValue());
} catch (final IllegalStateException e) {
/**
* 公式计算结果是不是纯数字
*/
cellValue = String.valueOf(cell.getRichStringCellValue());
}
/**
* 这句获取的是计算公式
*/
//cellValue = cell.getCellFormula() + "";
break;
case BLANK: // 空值
cellValue = "BLANG";
break;
case ERROR: // 故障
cellValue = "N/A";
break;
default://未知类型
cellValue = "ERROR";
}
System.out.println(" cellValue---> " + cellValue);
}
}
}
/**
*
*解析一个单元格得到数据
* @param cell
* @return
*/
private static String getCellContentAsString(final Cell cell) {
if (null == cell) {
return "";
}
/**
* 获取单元格格式类型
* POI 3.15 beta 3. Use CellType.ERROR instead.
*/
String cellValue = "";
switch (cell.getCellTypeEnum()) {
case STRING:// 字符串
cellValue = cell.getRichStringCellValue().getString().trim();
break;
case NUMERIC:// 数字
//如果为时间格式的内容
if (HSSFDateUtil.isCellDateFormatted(cell)) {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
cellValue = sdf.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue())).toString();
break;
} else {
/**
* 解决科学计数法的问题
*/
final Double d = cell.getNumericCellValue();
final DecimalFormat dformat = new DecimalFormat("#.##");
cellValue = dformat.format(d);
}
break;
case BOOLEAN:// Boolean
cellValue = String.valueOf(cell.getBooleanCellValue()).trim();
break;
case FORMULA:// 公式
/**
* 解决公式的取值问题
*/
try {
/**
* 公式计算结果是纯数字
*/
cellValue = String.valueOf(cell.getNumericCellValue());
} catch (final IllegalStateException e) {
/**
* 公式计算结果是不是纯数字
*/
cellValue = String.valueOf(cell.getRichStringCellValue());
}
/**
* 这句获取的是计算公式
*/
//cellValue = cell.getCellFormula() + "";
break;
case BLANK: // 空值
cellValue = "BLANG";
break;
case ERROR: // 故障
cellValue = "N/A";
break;
default://未知类型
cellValue = "";
}
return cellValue;
}
/**
*
* 读取已有Excel作为模板进行数据操作
* @param filePAth 模板路径
* @return -1:filePAth error;
* @throws IOException
* @throws FileNotFoundException
*/
public static int readTempleteExcel(final String filePAth,HttpServletResponse response) throws FileNotFoundException,IOException {
if ((filePAth == null) || filePAth.trim().isEmpty()) {
return -1;
}
/**
* 先读取模板 ,使用POIFSFileSystem对象构造的新HSSFWorkbook对象。
*/
final POIFSFileSystem POIfs = new POIFSFileSystem(new FileInputStream(filePAth));
/**
* 基于模板创建workbook
*/
final HSSFWorkbook workbook = new HSSFWorkbook(POIfs);
/**
* 如果模板存在多页的话可以分别取到
*/
final HSSFSheet sheet_1st = workbook.getSheetAt(0);
//////////////////////------------------------
// 第一页,第一行
final HSSFRow row = sheet_1st.getRow(0);
// 取第一个单元格
final HSSFCell cell = row.getCell(0);
// 获取单元格字符串值
final String cellValue = cell.getStringCellValue();
System.out.println(cellValue);
//final String path = "G:/POI_JAVA/demo.xls";
// 输出Excel
HttpServletResponse newresponse=response;
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
workbook.write(os);// HSSFWorkbook写入流
byte[] content = os.toByteArray();
InputStream is = new ByteArrayInputStream(content);
//文件名字符编码转换
//String strName = new String(filename.getBytes("UTF-8"),"ISO-8859-1");
// 设置请求
// 设置response参数,可以打开下载页面
newresponse.reset();
newresponse.setContentType("application/octet-stream");
newresponse.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode("aa.xls","UTF-8"));
OutputStream outputStream = newresponse.getOutputStream();// 打开流
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
bis = new BufferedInputStream(is);
bos = new BufferedOutputStream(outputStream);
byte[] buff = new byte[2048];
int bytesRead;
// Simple read/write loop.
while (-1 != (bytesRead = bis.read(buff,buff.length))) {
bos.write(buff,bytesRead);
}
if (bis != null){
bis.close();
}
if (bos != null){
bos.close();
}
outputStream.flush();// 刷新流
outputStream.close();// 关闭流
workbook.close();
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}
}
================== (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|