【问题标题】:Create an excel file for users to download using Apache POI使用 Apache POI 创建供用户下载的 excel 文件
【发布时间】:2012-06-27 12:49:11
【问题描述】:

我可以使用 apache poi 创建一个 excel 文件。但是,我希望用户能够将其下载为“真正的”excel 文件。我想要达到的效果是有一个弹出框允许用户下载文件。这类似于使用

<%@ page contentType="application/vnd.ms-excel" pageEncoding="ISO-8859-1"%> 
<%response.setHeader("Content-Disposition", "attachment;filename=myfile.xls"); %>

有一个严重的例外:我必须允许用户下载正确的 Excel 文件。我在某处读到上面的代码只是告诉客户端服务器正在发送一个 excel 文件

【问题讨论】:

    标签: jsp servlets apache-poi


    【解决方案1】:

    在普通的 servlet 而不是 JSP 文件中完成这项工作。 JSP 文件用于动态生成 HTML 代码,并且为此使用字符编写器而不是二进制输出流,因此只会损坏 POI 生成的 Excel 文件,该文件本质上是二进制流。

    所以,基本上你在servlet的doGet()方法中需要做的事情如下:

    response.setContentType("application/vnd.ms-excel");
    response.setHeader("Content-Disposition", "attachment; filename=filename.xls");
    HSSFWorkbook workbook = new HSSFWorkbook();
    // ...
    // Now populate workbook the usual way.
    // ...
    workbook.write(response.getOutputStream()); // Write workbook to response.
    workbook.close();
    

    现在,要下载它,请通过其 URL 而不是 JSP 文件调用 servlet。

    【讨论】:

    • writableworkbook 是 jexcel api 的一部分,对吗?即使我使用 poi 也应该可以工作吗?
    • @user571099 工作簿在这里是HSSFWorkbook,而不是WritableWorkbook
    • 这正是我想要的!我认为这可以通过 Jersey RESTful Web 服务类似地完成?
    • “响应”实例是什么样的对象?它是从哪个类实例化的?
    • @Stravos:在你的 servlet 中。如果您不知道“servlet”是什么,请退后一步,将 [servlets] 标签悬停在问题下方,直到出现黑色弹出框,然后在 info 链接中单击此处。
    【解决方案2】:

    虽然使用 servlet 而不是 jsp 编写二进制附件确实更常见,但当然可以从 jsp 编写二进制附件。这样做的好处是您不必担心配置 web.xml 或重新加载您的应用程序。这可能是一个重要的考虑因素,具体取决于您的 Web 服务器环境。

    这是一个使用 poi 将二进制附件发送到浏览器的示例 jsp。

    <%@page import="org.apache.poi.hssf.usermodel.*" %><%@page import="java.io.*" %><%
    
    // create a small spreadsheet
    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet();
    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = row.createCell(0);
    cell.setCellValue("Some text");
    
    // write it as an excel attachment
    ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
    wb.write(outByteStream);
    byte [] outArray = outByteStream.toByteArray();
    response.setContentType("application/ms-excel");
    response.setContentLength(outArray.length);
    response.setHeader("Expires:", "0"); // eliminates browser caching
    response.setHeader("Content-Disposition", "attachment; filename=testxls.xls");
    OutputStream outStream = response.getOutputStream();
    outStream.write(outArray);
    outStream.flush();
    
    %>
    

    重要的技巧是确保在开始代码的“

    另外,我建议您始终设置内容长度。如果未设置,某些浏览器将无法正常工作。这就是为什么我首先将电子表格输出到一个字节数组,这样我就可以在实际发送数据之前设置长度。

    【讨论】:

    • 谢谢您的回答,但请问您在哪里定义 xls 文件的路径?我的意思是,jsp 是如何知道从哪里选择 xls 文件的?它可以与之前由java程序创建的pdf一起使用吗?
    【解决方案3】:

    如果你想下载不要使用 hssf 工作簿,使用 apche poi 3.17 beta-1 会变慢并占用更多空间

    SXSSFWorkbook workbook = new SXSSFWorkbook(100); 
    workbook.setCompressTempFiles(true);
    Sheet sh = workbook.createSheet();
    //write your data on sheet
    
    //below code will download file in browser default download folder
    response.setContentType("application/vnd.ms-excel");
                response.setHeader("Content-Disposition", "attachment; filename="+filename+".xlsx");
                workbook.write(response.getOutputStream());
                workbook.close();
                workbook.dispose();
    

    对于 Pdf 使用 Itext

         Document document = new Document();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                PdfWriter.getInstance(document, baos);
                document.open(); 
    //write your code
    
     document.add("content");
                document.close();
                response.setHeader("Expires", "0");
                response.setHeader("Cache-Control","must-revalidate, post-check=0, pre-check=0");
                response.setHeader("Pragma", "public");
                response.setContentType("application/pdf");
                response.addHeader("Content-Disposition", "attachment; filename="+filename+".pdf");
                response.setContentLength(baos.size());
                OutputStream os = response.getOutputStream();
                baos.writeTo(os);
                os.flush();
                os.close();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-07
      • 1970-01-01
      • 2023-03-30
      • 2013-03-22
      • 2015-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多