AJAX实现Excel文件下载

前端之家收集整理的这篇文章主要介绍了AJAX实现Excel文件下载前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

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;
	}
}


==================

猜你在找的Ajax相关文章