如何修复损坏要下载的 xls 文件的 ExternalContext 调用?

How to fix ExternalContext call that corrupts xls file to download?

我有一个使用 jett 生成报告并为用户显示文件下载对话框的方法:

    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    externalContext.responseReset();
    externalContext.setResponseContentType("application/vnd.ms-excel");
    externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"" + "precificacao.xls" + "\"");

    //map beans omitted

    FileOutputStream saida = null;
    try {
        saida = new FileOutputStream(getClass().getResource("/.").getPath() + "/precificacao.xls");
    } catch (IOException e) {
        System.err.println(getClass().getResource("/.").getPath() + "/precificacao.xls" + ": " + e.getMessage());
    }

    InputStream entrada = null;
    try {

        entrada = new BufferedInputStream(new FileInputStream(getClass().getResource("/template.xls").getFile()));

        ExcelTransformer transformer = new ExcelTransformer();
        Workbook workbook = transformer.transform(entrada, beans);
        workbook.write(saida);

        saida.flush();
        saida.close();

        facesContext.responseComplete();
    } //catch ommitted

下载的文件已经损坏,为文本文档,没有任何字节: print

在此下载对话框例程之前,xls 是正常生成的,所以我认为是 setResponseContentType 出错了,尽管我在 xls 的正确命名法中看到了 link:http://www.iana.org/assignments/media-types

知道您没有将excel的内容写入响应吗?所以响应实际上是空的,因此会导致各种奇怪的行为。

你甚至自己写这个:

without any byte

你在图像中有它...

对于 PDF、图像甚至纯文本文件,您可能会遇到同样的问题(尽管不会给出错误,只是为空)

您甚至会在使用普通 servlet 时遇到同样的问题。因此,实际上您的所有标签(excel、jsf、jsf-2、xls)都与问题无关。缩小范围。

从上下文获取输出流并将工作簿写入该流应该可以解决这个问题。

OutputStream saida = externalContext.getResponseOutputStream(); 

我是这样解决的

public void createRelatorioFichaTecnica(Produto produto) throws IOException {

FacesContext facesContext = FacesContext.getCurrentInstance();

ExternalContext externalContext = facesContext.getExternalContext();
externalContext.responseReset(); 
externalContext.setResponseContentType("application/vnd.ms-excel"); 
externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"" + "precificacao.xls" + "\""); 

//map beans omitted
OutputStream saida = externalContext.getResponseOutputStream(); 
try{

    InputStream entrada = new BufferedInputStream(new FileInputStream(getClass().getResource("/template.xls").getFile())); 

    ExcelTransformer transformer = new ExcelTransformer(); 
    Workbook workbook = transformer.transform(entrada, beans); 
    workbook.write(saida);

    saida.flush();
    saida.close();

    facesContext.responseComplete();
 } 
 //catch omitted
}