Primefaces中使用p:fileDownload和datatable

3
我有一个datatable,它返回文件夹中的所有文件,可以使用primefaces p:filedownload资源下载该文件。
这很好用,但当加载代码时,我无法修改该文件,因为FileInputStream已经打开。如果在datatable加载期间关闭FileInputStream,则p:filedownload将无法正常工作。
有人能帮忙吗?
(如果我取消注释,filedownload将无法工作,如果保留注释,则无法通过Windows编辑文件)
Java:
public List<StreamedContent> getAnexosQuestionarios() {
List<StreamedContent> resultado = new ArrayList<StreamedContent>();
File[] arquivos = FileHelper.listarArquivos(selected.getEmpresa().getDiretorio(), FileHelper.QUESTIONARIOS);

if (arquivos != null) {
    for (File arquivo : arquivos) {
    InputStream stream = null;
    try {
        stream = new FileInputStream(arquivo.getAbsolutePath());
        String extensao = arquivo.getName().substring(arquivo.getName().lastIndexOf(".") + 1);

        StreamedContent file = new DefaultStreamedContent(stream,
        MimeTypes.valueOf(extensao).getMimeType(),
        arquivo.getName());
        resultado.add(file);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    }
    // try {
    // stream.close();
    // } catch (IOException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
}
return resultado;
}

HTML:

<p:panel header="Questionários">
                    <p:dataTable id="dtAnexosQuestionarios"
                        value="#{tecnologiaEmpresaController.anexosQuestionarios}"
                        var="arquivo" widgetVar="dtAnexosQuestionarios"
                        emptyMessage="Nenhum anexo disponível"
                        style="width:50%; border:2 !important; border-color:white !important;">
                        <p:column headerText="" style="width:20px;">
                            <h:graphicImage
                                value="../resources/images/#{tecnologiaEmpresaController.getExtensao(arquivo.name)}.png" />
                        </p:column>
                        <p:column headerText="Arquivo">
                            <p:commandLink id="downloadLink" value="#{arquivo.name}"
                                ajax="false">
                                <p:fileDownload value="#{arquivo}" />
                            </p:commandLink>
                        </p:column>
                    </p:dataTable>
                </p:panel>

谢谢!
2个回答

4

感谢sabrina.bettini帮我解决了这个问题。

这是我修复后的代码:

用于填充数据表的代码:

    public List<StreamedContent> getAnexosInformacoes() {
List<StreamedContent> resultado = new ArrayList<StreamedContent>();
File[] arquivos = FileHelper.listarArquivos(selected.getEmpresa().getDiretorio(), FileHelper.INFORMACOES);

if (arquivos != null) {
    for (File arquivo : arquivos) {
    InputStream stream = null;
    try {
        stream = new FileInputStream(arquivo.getAbsolutePath());
        String extensao = arquivo.getName().substring(arquivo.getName().lastIndexOf(".") + 1);

        StreamedContent file = new DefaultStreamedContent(stream,MimeTypes.valueOf(extensao).getMimeType(),arquivo.getName());
        resultado.add(file);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    try {
        stream.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }
}

return resultado;
}

使用ActionListener打开文件的代码:

StreamedContent arquivo;

public void prepararArquivoInformacoes(final StreamedContent arq) {
InputStream stream = null;
String caminho = FileHelper.retornarCaminhoPasta(selected.getEmpresa().getDiretorio(), FileHelper.INFORMACOES);
try {
    stream = new FileInputStream(caminho + File.separator + arq.getName());
    this.arquivo = new DefaultStreamedContent(stream, MimeTypes.valueOf("pdf").getMimeType(), arq.getName());
} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
}

public StreamedContent getArquivo() {
return arquivo;
}

HTML:

        <p:panel header="Informações">
                <p:dataTable id="dtAnexosInformacoes"
                    value="#{tecnologiaEmpresaController.anexosInformacoes}"
                    var="arquivo" widgetVar="dtAnexosInformacoes"
                    emptyMessage="Nenhum anexo disponível"
                    style="width:50%; border:2 !important; border-color:white !important;">
                    <p:column headerText="" style="width:20px;">
                        <h:graphicImage
                            value="../resources/images/#{tecnologiaEmpresaController.getExtensao(arquivo.name)}.png" />
                    </p:column>
                    <p:column headerText="Arquivo">
                        <p:commandLink id="downloadLink" value="#{arquivo.name}" 
                            ajax="false" actionListener="#{tecnologiaEmpresaController.prepararArquivoInformacoes(arquivo)}">
                            <p:fileDownload value="#{tecnologiaEmpresaController.arquivo}" />
                        </p:commandLink>
                    </p:column>
                </p:dataTable>
            </p:panel>
        </p:panel>

文件助手:

static FileService fileService;

public static final String PASTA_RAIZ = "P:\\";
public static final String INFORMACOES = "1. Informacoes";
public static final String QUESTIONARIOS = "2. Questionarios";
public static final String RELATORIOS = "3_Relatorio";

public static File[] listarArquivos(final String empresa, final String tipo) {
File file = new File(PASTA_RAIZ + empresa + File.separator + tipo + File.separator);
return file.listFiles();
}

public static String retornarCaminhoPasta(final String empresa, final String tipo) {
File file = new File(PASTA_RAIZ + empresa + File.separator + tipo + File.separator);
return file.getAbsolutePath();
}

3

尝试使用以下代码:

StreamedContent file = new DefaultStreamedContent(stream,"application/octet-stream", arquivo.getName());

在我的应用程序中,我是这样做的:

我不使用datatable。我使用ui:repeat来迭代ArquivoAnexo列表。

<ui:repeat value="#{lista}" var="arquivo" varStatus="status">

<h:commandLink actionListener="#{cadastrarBean.prepararDownloadArquivo(arquivo)}" styleClass="downloadArquivoAnexo">
    <p:fileDownload value="#{cadastrarBean.arquivoParaDownload}"/>
</h:commandLink>


public void prepararDownloadArquivo(ArquivoAnexo arquivo) {
    byte[] conteudo = arquivo.getArquivo();
    String nome = arquivo.getNomeArquivo();
    this.arquivoParaDownload = new DefaultStreamedContent(new ByteArrayInputStream(conteudo), "application/octet-stream", nome);
}

public StreamedContent getArquivoParaDownload() {
    return arquivoParaDownload;
}

public interface ArquivoAnexo {    
    byte[] getArquivo();    
    String getNomeArquivo();
    String getDescricao();    
    void setDescricao(String descricao);
    void setArquivo(byte[] conteudo);    
    void setNomeArquivo(String nome);
}

你好,Sabrina!我遇到了同样的错误:“读取错误”。问题就在于“new FileInputStream”……如果我关闭它,我就无法打开文件,但如果我保持它,我就无法修改文件。 - Pellizon
我在我的应用程序中也是这样做的,但我从未尝试过编辑已下载的文件。您想修改服务器上的文件吗?还是只想下载它,然后在本地修改? - sabrina.bettini
我想要更改服务器上的文件,这样用户就始终拥有最新的文件。 - Pellizon
我认为你需要下载该文件,然后将其上传回服务器。 - sabrina.bettini
你好Sabrina,使用你的例子我终于知道如何让它工作了!似乎StreamedContent没有按照预期工作,但现在没问题了!非常感谢你! - Pellizon
它真的在服务器上更改文件吗? - sabrina.bettini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接