Excel apache POI 3.8出现无法读取的内容错误

Excel apache POI 3.8出现无法读取的内容错误,excel,jsp,excel-2007,apache-poi,Excel,Jsp,Excel 2007,Apache Poi,我正在使用ApachePOI3.8。我有一个生成excel(.xslx)文件的JSP。我在本地开发了它,文件可以毫无问题地打开。 然后,我在Dev环境中部署了该应用程序,当我在那里打开生成的excel文件时,会出现一个警告框:“excel在ausencias.xlsx中发现不可读的内容。是否要恢复此工作簿的内容?如果您信任此工作簿的源,请单击“是” 如果单击“是”,则会出现以下警报:“无法使用Microsoft Excel打开此文件。是否要在Microsoft Office Online网站上搜

我正在使用ApachePOI3.8。我有一个生成excel(.xslx)文件的JSP。我在本地开发了它,文件可以毫无问题地打开。 然后,我在Dev环境中部署了该应用程序,当我在那里打开生成的excel文件时,会出现一个警告框:“excel在ausencias.xlsx中发现不可读的内容。是否要恢复此工作簿的内容?如果您信任此工作簿的源,请单击“是” 如果单击“是”,则会出现以下警报:“无法使用Microsoft Excel打开此文件。是否要在Microsoft Office Online网站上搜索可打开此文件的转换器?” 如果单击“否”,则文件已正确打开。但我不知道为什么我会犯这些错误

即使生成一个简单的空.xslx文件,也会发生这种情况:

<%@page import="java.io.FileOutputStream"%>
<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@page import="java.io.IOException"%>
<%@page import="javax.servlet.*"%>

<%@page import="org.apache.poi.ss.usermodel.*"%>    
<%@page import="org.apache.poi.ss.util.CellRangeAddress"%>
<%@page import="org.apache.poi.xssf.usermodel.*"%>

<%
    response.setHeader ("Content-Disposition", "attachment;filename=\"ausencias.xlsx\"");
    response.setContentType("application/vnd.ms-excel");

    Workbook wb = new XSSFWorkbook();

    Sheet sheet = wb.createSheet("Ausencias");

    ServletOutputStream fout = response.getOutputStream();

    wb.write(fout);
    fout.flush();
    fout.close();
%>

在我的本地计算机中,我有Microsoft Office Excel 2007(12.0.6661.5000)SP2 MSO(12.0.6562.5003) 在开发环境中,我有MicrosoftOfficeExcel2007(12.0.6611.1000)SP3MSO(12.0.6607.1000)

有人知道解决方案或解决方法吗

谢谢

编辑:我已经添加了整个JSP代码。我知道有些进口产品可能不会被使用;当我裁剪我的原始代码寻找问题时,我就把它们放在那里了


编辑2:我在本地机器上打开了在开发环境中生成的文档,它抛出了相同的警告。因此,问题出在文件中,而不是Excel版本中。似乎有什么东西在篡改Dev Env中的文件。有什么想法吗?

我发现,无论何时将二进制文件作为http响应发回,都应该设置内容长度。虽然有时您可以不设置长度就离开,但浏览器通常无法可靠地自动计算文件的长度

通常,我这样做的方式是首先将输出文件写入ByteArrayOutputStream。这让我可以计算输出文件有多大。然后,我将ByteArrayOutputStream字节写入响应对象

以下是一个基于原始代码的示例:

    // generate the xlsx file as a byte array
    Workbook wb = new XSSFWorkbook();
    Sheet sheet = wb.createSheet("Ausencias");
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    wb.write(bout);
    bout.close();

    // send byte array as response
    response.setHeader ("Content-Disposition", "attachment;filename=\"ausencias.xlsx\"");
    response.setContentType("application/vnd.ms-excel");
    response.setContentLength(bout.size());
    ServletOutputStream fout = response.getOutputStream();
    fout.write(bout.toByteArray());
    fout.flush();
    fout.close();

我发现,无论何时将二进制文件作为http响应发回,都应该设置内容长度。虽然有时您可以不设置长度就离开,但浏览器通常无法可靠地自动计算文件的长度

通常,我这样做的方式是首先将输出文件写入ByteArrayOutputStream。这让我可以计算输出文件有多大。然后,我将ByteArrayOutputStream字节写入响应对象

以下是一个基于原始代码的示例:

    // generate the xlsx file as a byte array
    Workbook wb = new XSSFWorkbook();
    Sheet sheet = wb.createSheet("Ausencias");
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    wb.write(bout);
    bout.close();

    // send byte array as response
    response.setHeader ("Content-Disposition", "attachment;filename=\"ausencias.xlsx\"");
    response.setContentType("application/vnd.ms-excel");
    response.setContentLength(bout.size());
    ServletOutputStream fout = response.getOutputStream();
    fout.write(bout.toByteArray());
    fout.flush();
    fout.close();

出现此错误的原因是MIME类型错误。而不是

“应用程序/vnd.ms excel”

你需要使用

“application/vnd.openxmlformats of iceDocument.spreadsheetml.sheet”


对于XLSX文档,出现此错误的原因是MIME类型错误。而不是

“应用程序/vnd.ms excel”

你需要使用

“application/vnd.openxmlformats of iceDocument.spreadsheetml.sheet”


对于XLSX文档

这是我解决问题的方法:

String name = "Name_of_file.xlsx";

ByteArrayOutputStream bout = new ByteArrayOutputStream();
workbook.write(bout);
bout.close();

response.setHeader("Set-Cookie", "fileDownload=true; path=/");
response.setHeader("Content-Disposition", "attachment; filename=" + name);
response.setContentLength(bout.size());

ServletOutputStream out = response.getOutputStream();

out.write(bout.toByteArray());
out.flush();
out.close();

我认为与其他答案的区别在于我没有使用response.setContentType指令,我不知道它工作的确切原因。。。但它奏效了。不再显示“Excel发现无法读取的内容…”消息。

这是我解决问题的方法:

String name = "Name_of_file.xlsx";

ByteArrayOutputStream bout = new ByteArrayOutputStream();
workbook.write(bout);
bout.close();

response.setHeader("Set-Cookie", "fileDownload=true; path=/");
response.setHeader("Content-Disposition", "attachment; filename=" + name);
response.setContentLength(bout.size());

ServletOutputStream out = response.getOutputStream();

out.write(bout.toByteArray());
out.flush();
out.close();


我认为与其他答案的区别在于我没有使用response.setContentType指令,我不知道它工作的确切原因。。。但它奏效了。不再显示“Excel发现无法读取的内容…”消息。

如果保存文件,而不是在Excel中打开文件,文件大小是否正确?那门开得好吗?前面有垃圾字符吗?如果我保存它,也会发生同样的情况。这是正确的大小,因为在所有这些警告之后,文件已正确打开。您确定两个服务器上的POI版本相同吗?不可能有旧版本的POI JAR被替代使用?是的,它们是完全相同的库。如果保存文件,而不是在Excel中打开文件,其大小是否正确?那门开得好吗?前面有垃圾字符吗?如果我保存它,也会发生同样的情况。这是正确的大小,因为在所有这些警告之后,文件已正确打开。您确定两个服务器上的POI版本相同吗?没有可能会有一个旧版本的POI JAR被用来替代?是的,它们是完全相同的库。我感谢你的帮助,但即使有你的建议,问题仍然存在。无论如何谢谢你!我错过了你说的是jsp的事实。上面的代码在一个servlet中。我有另一个想法,为什么它可能会失败。如果看不到确切的jsp源代码,很难解释或验证。首先,我建议您在servlet中尝试您的代码,看看这是否有效。然后,如果您使用将确切的jsp代码上载到我的服务器,我可能会进一步帮助您。当您返回非html数据时,您必须非常小心jsp的实际格式。例如,所有的include都必须在一行上,而yes是一个JSP。此外,我不能在servlet中尝试代码,因为我们不允许接触servlet(我们甚至没有访问它们的权限)。因此,我们只能使用JSP来实现这一点。谢谢你的帮助!如果您想给我发送实际的jsp,很可能只是格式问题。基本上,我感谢你的帮助,但问题仍然存在,即使有你的建议。无论如何谢谢你!我错过了你说的是jsp的事实。上面的代码在一个servlet中。我有另一个想法,为什么它可能会失败。如果看不到确切的jsp源代码,很难解释或验证。首先,我建议您在servlet中尝试您的代码,看看这是否有效。然后,如果您使用将您的确切jsp代码上载到我的服务器,我可能会进一步帮助您