Скачать файл из дерева простых лиц - PullRequest
0 голосов
/ 22 декабря 2011

Это мой xhtml-code

        <p:tree value="#{documentsController.root}"
                var="node" selectionMode="single"
                dynamic="true">

            <p:treeNode 
                expandedIcon="ui-icon-folder-open"
                collapsedIcon="ui-icon-folder-collapsed">
                <h:outputText value="#{node}" />
            </p:treeNode>

            <p:treeNode type="file" icon="ui-icon-document">
                <h:outputText value="#{node}"/>
            </p:treeNode>

            <p:ajax event="select" listener="#{documentsController.onNodeSelect}"/>

        </p:tree>

, и это базовый компонент

@ManagedBean
@ViewScoped
public class DocumentsController implements Serializable {

    TreeNode root;
    //TreeNode[] selectedNodes;

    @PostConstruct
    public void init() {

        root = new DefaultTreeNode("SRC", null);

        TreeNode node0 = new DefaultTreeNode("A", root);
        TreeNode node1 = new DefaultTreeNode("B", root);
        TreeNode node2 = new DefaultTreeNode("C", root);

        TreeNode node3 = new DefaultTreeNode("file", "D", node0);
        TreeNode node4 = new DefaultTreeNode("file", "E", node0);
        TreeNode node5 = new DefaultTreeNode("file", "F", node0);

        String p = "C:\\Users\\federico.martinez\\Desktop\\a.wmv";

        TreeNode node6 = new DefaultTreeNode("file", new File(p), node1);
        TreeNode node7 = new DefaultTreeNode("file", "h", node1);
        TreeNode node8 = new DefaultTreeNode("file", "i", node1);

    }

    public TreeNode getRoot() {
        return root;
    }

    /*
    public void setSelectedNodes(TreeNode[] selectedNodes){
    this.selectedNodes = selectedNodes;
    }

    public TreeNode[] getSelectedNodes(){
    return selectedNodes;
    }*/
    public void onNodeSelect(NodeSelectEvent event) {
        if (event.getTreeNode().getType().equals("file")) {
            File file = new File(event.getTreeNode().getData().toString());
            FacesContext facesContext = FacesContext.getCurrentInstance();
            ExternalContext externalContext = facesContext.getExternalContext();

            externalContext.setResponseHeader("Content-Type", externalContext.getMimeType(file.getName()));
            externalContext.setResponseHeader("Content-Length", String.valueOf(file.length()));
            externalContext.setResponseHeader("Content-Disposition", "attachment;filename=\"" + file.getName() + "\"");

            InputStream input = null;
            OutputStream output = null;

            try {
                input = new FileInputStream(file);
                output = externalContext.getResponseOutputStream();
                IOUtils.copy(input, output);
            } catch (FileNotFoundException ex) {
                System.out.println("FileNotFound: " + ex.getMessage());
            } catch (IOException ex) {
                System.out.println("IO: " + ex.getMessage());
            } finally {
                IOUtils.closeQuietly(output);
                IOUtils.closeQuietly(input);
            }
            facesContext.responseComplete();
        }
    }
}

Но это не загрузка файла, я использовал этот метод загрузки с деревом Томагавки это сработало, теперь я пытаюсь с PrimeFaces, но это не загружает файл и без ошибок!

любой совет, что может быть не так?

Заранее спасибо!

ОБНОВЛЕНИЕ

У меня есть эта модификация, но я не могу заставить ее загрузить файл.

        <p:tree value="#{documentsController.root}"
                var="node" selectionMode="single"
                dynamic="true">

            <p:treeNode 
                expandedIcon="ui-icon-folder-open"
                collapsedIcon="ui-icon-folder-collapsed">
                <h:outputText value="#{node}" />
            </p:treeNode>

            <p:treeNode type="file" icon="ui-icon-document">
                <p:commandButton value="#{node}" ajax="false">
                    <p:fileDownload value="#{documentsController.download(node)}" />
                </p:commandButton>
            </p:treeNode>

        </p:tree>

, а бэкан

public void download(String path) {

    File f = new File(path);
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();

    InputStream is = ((ServletContext)externalContext.getContext()).getResourceAsStream(path);

    file = new DefaultStreamedContent(is, externalContext.getMimeType(f.getName()), f.getName());   

}

public StreamedContent getFile(){
    return file;
}

1 Ответ

2 голосов
/ 22 декабря 2011

Ваша первая проблема - вы пытаетесь загрузить файл по запросу Ajax. Это невозможно. Ajax выполняется и управляется кодом JavaScript. В JavaScript из-за ограничений безопасности нет средств для запуска диалога Сохранить как . Вместо этого вам нужно запустить полноценный синхронный запрос. Исходная страница в любом случае останется прежней, если для размещения содержимого установлено значение attachment.

Итак, вам нужно как минимум <h:commandButton> или <p:commandButton ajax="false">.

Ваша вторая проблема, с которой вы столкнулись при попытке использовать <p:fileDownload>, заключается в том, что value должен указывать на метод, возвращающий StreamedContent, а не void. Вы связали его с void методом и, следовательно, ничего не будет возвращено.

Итак, вам нужно вернуть StreamedContent на <p:fileDownload> значение.

Ваша третья проблема заключается в том, что вы получаете файл как ресурс classpath ServletContext#getResourceAsStream() (который, как я полагаю, вы слепо копировали из примера демонстрации PrimeFaces, который, в свою очередь, сам по себе также довольно беден, он мог просто использовать ExternalContext#getResourceAsStream() вместо этого без необходимости извлекать ServletContext из-под колпаков JSF, но это в сторону) вместо FileInputStream, как в исходном коде.

Итак, любое из этих решений должно помочь:

<p:treeNode type="file" icon="ui-icon-document">
    <p:commandButton value="#{node}" ajax="false">
        <p:fileDownload value="#{documentsController.download(node)}" />
    </p:commandButton>
</p:treeNode>

с

public StreamedContent download(String path) {
    File file = new File(path);
    InputStream input = new FileInputStream(file);
    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    return new DefaultStreamedContent(input, externalContext.getMimeType(file.getName()), file.getName());   
}

или

<p:treeNode type="file" icon="ui-icon-document">
    <h:commandButton value="#{node}" action="#{documentsController.download(node)}" />
</p:treeNode>

с исходным методом onNodeSelect() с аргументом, измененным на String path.

...