JAVA:利用Apache poi在服务器传输带有数据和图片的excel的数据流至浏览器供其下载至本地

如题,编程语言为java,利用Apache poi在服务器端生成带有数据和图片的excel的数据流至浏览器供其下载至本地,基本就是类似一个网站的数据导出功能。
主要参考网址:http://blog.csdn.net/sinat_22767969/article/details/50644648
基本主要代码是参考以上的网址的,本人在此基础上做了一些小的修改,就是使导出的图片呈比例的展示以及我本身的图片是从ftp上获取下来的,因此在插入的时候转换成字节流插入就好,还有就是自己根据自己所需生成表格的格式做些修改,这个就不明讲,自己看代码就好
先说步骤:
1、把自己所要生成excel表格的数据统一存放进List表中,我这边是放一个实体类
2、在前端请求导出数据的时候, 再用自己已经生成号的List表数据去调用生成excel表格数据流传输至前方即可
3、前端最好用GET请求后台,这样前端可以直接调用后台该接口即可在浏览器完成下载,至于POST方法,本人没试成功,具体原因也不清楚。。。。
废话少说,show you code:
(1)设置excel的类

import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import cn.recour.wiicop.db.entity.JYZTVio;//需要导出数据的实体类

/** 
 *  
 * @类名: ExportToExcelUtil 
 * @描述: 设置excel'的信息 
 * 
 */  
public class ExportToExcelUtil {  
    public static void out(HttpServletResponse response, List list,String fileName)  
            throws Exception {  
        /** 
         * 指定下载名 
         */  
//        String fileName = "违停拍数据.xls";  
        /** 
         * 编码 
         */  
        fileName = new String(fileName.getBytes("UTF-8"), "UTF-8");
        /** 
         * 去除空白行 
         */  
        response.reset();  
        /** 
         * 指定下载的文件名与设置相应头 
         */ 
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename="  
                + fileName);  
        /** 
         * 下载文件类型 
         */  
        response.setContentType("application/vnd.ms-excel");  
        /** 
         * 别给我缓存 
         */  
        response.setHeader("Pragma", "no-cache");  
        response.setHeader("Cache-Control", "no-cache");  
        response.setDateHeader("Expires", 0);  
        /** 
         * 得到输出流,放到缓冲区  
         */  
        OutputStream output = response.getOutputStream();  
        BufferedOutputStream bufferedOutPut = new BufferedOutputStream(output);  

        /** 
         * 下面是导出的excel格式的设置 
         */  
        /*******************我是分割线**************************************/  


        // 定义单元格报头  
        String worksheetTitle = "违停拍数据";  

        HSSFWorkbook wb = new HSSFWorkbook();  

        // 创建单元格样式  
        HSSFCellStyle cellStyleTitle = wb.createCellStyle();  
        // 指定单元格居中对齐  
        cellStyleTitle.setAlignment(HSSFCellStyle.ALIGN_CENTER);  
        // 指定单元格垂直居中对齐  
        cellStyleTitle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);  
        // 指定当单元格内容显示不下时自动换行  
        cellStyleTitle.setWrapText(true);  
        HSSFCellStyle cellStyle = wb.createCellStyle();  
        // 指定单元格居中对齐  
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);  
        // 指定单元格垂直居中对齐  
        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);  
        // 指定当单元格内容显示不下时自动换行  
        cellStyle.setWrapText(true);  
        // 设置单元格字体  
        HSSFFont font = wb.createFont();  
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);  
        font.setFontName("宋体");  
        font.setFontHeight((short) 200);  
        cellStyleTitle.setFont(font);  

        /****************wo是分割线*****************************************/  

        /** 
         * 工作表列名 
         */  
        String id = "序号";  
        String cphm = "车牌号码";  
        String location = "违停地址";
        String time = "违停时间";
        String img = "违停照片";


        HSSFSheet sheet = wb.createSheet();  
        ExportExcelUtil exportExcel = new ExportExcelUtil(wb, sheet);  
        /** 
         * 创建报表头部 
         */  
        exportExcel.createNormalHead(worksheetTitle, 4);  
        // 定义第一行  
        HSSFRow row1 = sheet.createRow(1);  
        HSSFCell cell1 = row1.createCell(0);  

        /** 
         * 第一行第一列 
         */  

        cell1.setCellStyle(cellStyleTitle);  
        cell1.setCellValue(new HSSFRichTextString(id));  
        /** 
         * 第一行第二列 
         */  
        cell1 = row1.createCell(1);  
        cell1.setCellStyle(cellStyleTitle);  
        cell1.setCellValue(new HSSFRichTextString(cphm));  

        /** 
         * 第一行第三列 
         */  
        cell1 = row1.createCell(2);  
        cell1.setCellStyle(cellStyleTitle);  
        cell1.setCellValue(new HSSFRichTextString(location));  

        /** 
         * 第一行第四列 
         */  
        cell1 = row1.createCell(3);  
        cell1.setCellStyle(cellStyleTitle);  
        cell1.setCellValue(new HSSFRichTextString(time));  

        /** 
         * 第一行第五列 
         */  
        cell1 = row1.createCell(4);  
        cell1.setCellStyle(cellStyleTitle);  
        cell1.setCellValue(new HSSFRichTextString(img));  
        /********************我是分割线*********************************/  

        /** 
         * 定义第二行,就是我们的数据 
         */  
        HSSFRow row = sheet.createRow(2);  
        HSSFCell cell = row.createCell(1);  
        sheet.setColumnWidth(4, 30 * 256);//固定图片宽度大小为30*256,然后在下面设置图片以此宽度为基准设置高度
        /** 
         * 遍历我们传进来的jyztVio-list 
         */  
        JYZTVio jyztVio =null;  
        HSSFPatriarch patriarch = sheet.createDrawingPatriarch();  

        for (int i = 0; i < list.size(); i++) {  
            jyztVio = list.get(i);  
            /** 
             * 从i+2行开始,因为我们之前的表的标题和列的标题已经占用了两行 
             */  
            row = sheet.createRow(i + 2);  
            int s = i+1;  
            //...id  
            cell = row.createCell(0);  
            cell.setCellStyle(cellStyle);  
            cell.setCellValue(new HSSFRichTextString(s + ""));  
            //....车牌号码cphm  
            cell = row.createCell(1);  
            cell.setCellStyle(cellStyle);  
            cell.setCellValue(new HSSFRichTextString("\n"+jyztVio.getCphm()+"\n"));  
            //....违停地址  
            cell = row.createCell(2);  
            cell.setCellStyle(cellStyle);  
            cell.setCellValue(new HSSFRichTextString("\n"+jyztVio.getLocation()+"\n"));
            //....违停时间  
            cell = row.createCell(3);  
            cell.setCellStyle(cellStyle);  
            cell.setCellValue(new HSSFRichTextString("\n"+jyztVio.getTime()+"\n"));
            //...违停拍照  
            short h =2;//定义图片所在行  
            short l=4;//定义图片所在列  
            cell = row.createCell(4);  
            cell.setCellStyle(cellStyle);  
            //得到图片  new FileUtils().getFile(String path)这是我从ftp上获取图片的方法,里面参数是图片路径,各位具体情况具体处理
            InputStream sbs = new ByteArrayInputStream(new FileUtils().getFile(jyztVio.getImage()));
            BufferedImage image = ImageIO.read(sbs);
            ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();  
            int width = image.getWidth();//图片原始宽度
            int height = image.getHeight();//图片原始高度
            //根据宽度按比例设置高度
            height = (int) Math.round((height * (30 * 13) * 1.0 / width));
            row.setHeight((short) (height / 2 * 20));
            ImageIO.write(image, "jpg", byteArrayOut);  
            HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, l, i + h, (short) (l+1), (i+1) + h);  
            anchor.setAnchorType(3); 

            // 插入图片  
            patriarch.createPicture(anchor, wb.addPicture(  
                    byteArrayOut.toByteArray(),  
                    HSSFWorkbook.PICTURE_TYPE_JPEG));  

        }  
        try {  
            /** 
             * 输出到浏览器
             */  
            bufferedOutPut.flush();  
            wb.write(bufferedOutPut);  
            bufferedOutPut.close();//关流  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            list.clear();  
        }  
    }  
}  

(2)excel导出的工具类

/**
 * @author czy
 * @version 创建时间:2017年10月31日 下午5:37:17
 * 
 */
import java.io.File;  
import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  

import org.apache.poi.hssf.usermodel.HSSFCell;  
import org.apache.poi.hssf.usermodel.HSSFCellStyle;  
import org.apache.poi.hssf.usermodel.HSSFFont;  
import org.apache.poi.hssf.usermodel.HSSFRichTextString;  
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.hssf.util.HSSFColor;  
import org.apache.poi.hssf.util.Region;  

/** 
 *  
 * @类名: ExportExcel 
 * @描述: excel工具类 
 *  
 */  
public class ExportExcelUtil {  

    private HSSFWorkbook wb = null;  
    private HSSFSheet sheet = null;  

    /** 
     *  
     * 

* 标题: *

*

* 描述: *

* * @param wb * @param sheet */
public ExportExcelUtil(HSSFWorkbook wb, HSSFSheet sheet) { // super(); this.wb = wb; this.sheet = sheet; } /** * * @标题: createNormalHead * @描述: TODO(这里用一句话描述这个方法的作用) * @参数: @param headString 头部的字符 * @参数: @param colSum 报表的列数 * @返回: void 返回类型 * @抛出: */ @SuppressWarnings("deprecation") public void createNormalHead(String headString, int colSum) { HSSFRow row = sheet.createRow(0); // 设置第一行 HSSFCell cell = row.createCell(0); // row.setHeight((short) 1000); // 定义单元格为字符串类型 cell.setCellType(HSSFCell.ENCODING_UTF_16);// 中文处理 cell.setCellValue(new HSSFRichTextString(headString)); // 指定合并区域 /** * public Region(int rowFrom, short colFrom, int rowTo, short colTo) */ sheet.addMergedRegion(new Region(0, (short) 0, 0, (short) colSum)); // 定义单元格格式,添加单元格表样式,并添加到工作簿 HSSFCellStyle cellStyle = wb.createCellStyle(); // 设置单元格水平对齐类型 cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 指定单元格居中对齐 cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 指定单元格垂直居中对齐 cellStyle.setWrapText(true);// 指定单元格自动换行 // 设置单元格字体 HSSFFont font = wb.createFont(); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); font.setFontName("宋体"); font.setFontHeight((short) 600); cellStyle.setFont(font); cell.setCellStyle(cellStyle); } /** * * @标题: createNormalTwoRow * @描述: 创建通用报表第二行 * @参数: @param params 二行统计条件数组 * @参数: @param colSum 需要合并到的列索引 * @返回: void 返回类型 * @抛出: */ @SuppressWarnings("deprecation") public void createNormalTwoRow(String[] params, int colSum) { // 创建第二行 HSSFRow row1 = sheet.createRow(1); row1.setHeight((short) 400); HSSFCell cell2 = row1.createCell(0); cell2.setCellType(HSSFCell.ENCODING_UTF_16); cell2.setCellValue(new HSSFRichTextString("时间:" + params[0] + "至" + params[1])); // 指定合并区域 sheet.addMergedRegion(new Region(1, (short) 0, 1, (short) colSum)); HSSFCellStyle cellStyle = wb.createCellStyle(); cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 指定单元格居中对齐 cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 指定单元格垂直居中对齐 cellStyle.setWrapText(true);// 指定单元格自动换行 // 设置单元格字体 HSSFFont font = wb.createFont(); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); font.setFontName("宋体"); font.setFontHeight((short) 250); cellStyle.setFont(font); cell2.setCellStyle(cellStyle); } /** * * @标题: createColumHeader * @描述: 设置报表标题 * @参数: @param columHeader 标题字符串数组 * @返回: void 返回类型 * @抛出: */ public void createColumHeader(String[] columHeader) { // 设置列头 在第三行 HSSFRow row2 = sheet.createRow(2); // 指定行高 row2.setHeight((short) 600); HSSFCellStyle cellStyle = wb.createCellStyle(); cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 指定单元格居中对齐 cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 指定单元格垂直居中对齐 cellStyle.setWrapText(true);// 指定单元格自动换行 // 单元格字体 HSSFFont font = wb.createFont(); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); font.setFontName("宋体"); font.setFontHeight((short) 250); cellStyle.setFont(font); // 设置单元格背景色 cellStyle.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index); cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); HSSFCell cell3 = null; for (int i = 0; i < columHeader.length; i++) { cell3 = row2.createCell(i); cell3.setCellType(HSSFCell.ENCODING_UTF_16); cell3.setCellStyle(cellStyle); cell3.setCellValue(new HSSFRichTextString(columHeader[i])); } } /** * * @标题: cteateCell * @描述: 创建内容单元格 * @参数: @param wb HSSFWorkbook * @参数: @param row HSSFRow * @参数: @param col short型的列索引 * @参数: @param align 对齐方式 * @参数: @param val 列 * @返回: void 返回类型 * @抛出: */ public void cteateCell(HSSFWorkbook wb, HSSFRow row, int col, short align, String val) { HSSFCell cell = row.createCell(col); cell.setCellType(HSSFCell.ENCODING_UTF_16); cell.setCellValue(new HSSFRichTextString(val)); HSSFCellStyle cellstyle = wb.createCellStyle(); cellstyle.setAlignment(align); cell.setCellStyle(cellstyle); } /** * * @标题: createLastSumRow * @描述: 创建合计行 * @参数: @param colSum 需要合并到的列索引 * @参数: @param cellValue 设定文件 * @返回: void 返回类型 * @抛出: */ @SuppressWarnings("deprecation") public void createLastSumRow(int colSum, String[] cellValue) { HSSFCellStyle cellStyle = wb.createCellStyle(); cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 指定单元格居中对齐 cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 指定单元格垂直居中对齐 cellStyle.setWrapText(true);// 指定单元格自动换行 // 单元格字体 HSSFFont font = wb.createFont(); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); font.setFontName("宋体"); font.setFontHeight((short) 250); cellStyle.setFont(font); // 获取工作表最后一行 HSSFRow lastRow = sheet.createRow((short) (sheet.getLastRowNum() + 1)); HSSFCell sumCell = lastRow.createCell(0); sumCell.setCellValue(new HSSFRichTextString("合计")); sumCell.setCellStyle(cellStyle); // 合并 最后一行的第零列-最后一行的第一列 sheet.addMergedRegion(new Region(sheet.getLastRowNum(), (short) 0, sheet.getLastRowNum(), (short) colSum));// 指定合并区域 for (int i = 2; i < (cellValue.length + 2); i++) { // 定义最后一行的第三列 sumCell = lastRow.createCell(i); sumCell.setCellStyle(cellStyle); // 定义数组 从0开始。 sumCell.setCellValue(new HSSFRichTextString(cellValue[i - 2])); } } /** * * @标题: outputExcel * @描述: 输出excel下载 * @参数: @param fileName 文件名 * @返回: void 返回类型 * @抛出: */ public void outputExcel(String fileName) { FileOutputStream fos = null; try { fos = new FileOutputStream(new File(fileName)); wb.write(fos); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * * @返回: HSSFSheet 返回类型 */ public HSSFSheet getSheet() { return sheet; } public void setSheet(HSSFSheet sheet) { this.sheet = sheet; } /** * * @返回: HSSFWorkbook 返回类型 */ public HSSFWorkbook getWb() { return wb; } /** * */ public void setWb(HSSFWorkbook wb) { this.wb = wb; } }

Controller层的代码:

/**
     * 下载违停拍数据
     * @param body
     * @param request
     * @param response
     */
    @RequestMapping(value = "/downloaddata", method = RequestMethod.GET)
    public @ResponseBody void downloaddata(HttpServletRequest request,HttpServletResponse response){
        try {
            String fileName = request.getParameter("fileName");
            List jyztViolist = jyztVioService.downloaddata(request,response);
            if(jyztViolist==null){
                preJson(response,"无下载内容");
            }else{
                ExportToExcelUtil.out(response, jyztViolist, fileName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这样,前端只要调用该接口,就可以在浏览器完成下载功能。
注意:本人以上生成excel表和Excel工具类的代码基本是借鉴以上网址而来,只是根据自己功能需求做了一些改变,并没有想拿来做商业用途,如需要可删!
主要参考网址:http://blog.csdn.net/sinat_22767969/article/details/50644648

你可能感兴趣的:(excel工具类,Excel数据流)