Использование commandButton на странице jsf для загрузки файла - PullRequest
7 голосов
/ 02 декабря 2010

Использование команды Button на странице jsf для загрузки файла. Использование: JSF & Richfaces.

У меня есть таблица (расширяет ExtendedDataModel реализует Modifiable, Serializable) с некоторыми данными и в каждой строке кнопка «скачать».

<a4j:commandButton id="getDownload" value="download" 
    style="margin-left:10px;margin-right:10px;width:100px;"
    action="#{controller.download}" immediate="true" ajaxSingle="true">
    <f:setPropertyActionListener target="#{controller.idString}" value="#{item.id}" />                     
</a4j:commandButton>

Я должен собрать файл в контроллере:

public void download(){
 OutputStream out = null;
....

FacesContext fc = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
out = response.getOutputStream();

ZipOutputStream zipout = new ZipOutputStream(out);
.....

zipout.close();
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition", "attachment; filename=\""+filename+"\"");
out.flush();
....

} finally {
    try {
        if (out!=null){
            out.close();
        }
        FacesContext.getCurrentInstance().responseComplete();
    } catch (IOException e) {
        logger.error(e);
    }

}
...
}

Проблема началась, когда я реализовал ExtendedDataModel самостоятельно. Сначала я использовал h: commandLink, но метод контроллера никогда не вызывался ... я пытался и пытался ... теперь вызывается правильный метод, но содержимое (zip) файла отображается на странице. Мне нужна кнопка / ссылка на странице, которую пользователь может щелкнуть, чтобы загрузить файл. Сама страница не должна меняться. Есть идеи?

Я могу создать сервлет, но я не понимаю, почему ExtendedDataModel изменил поведение ссылок внутри.

Edit1

Я использовал

<h:commandLink id="getDownload" value="download" action="#{controller.download}">                                                       
                            <f:setPropertyActionListener target="#{controller.idString}" value="#{item.id}" />                              
                        </h:commandLink>

раньше. Он работает с «нормальной» таблицей richfaces, но не тогда, когда я использовал ее в своей собственной таблице, которая расширяет ExtendedDataModel.

Редактировать 2 - Решение / Обходной путь

Невозможно использовать h: commandButton, .. Link ... что угодно внутри собственной таблицы, чтобы загрузить файл. Сейчас я использую одну кнопку в таблице для рендеринга новой PanelGroup и вторую кнопку внутри новой PanelGroupt для загрузки файла. Я много гуглил за это, похоже на баг с богатым лицом.

Ответы [ 2 ]

10 голосов
/ 02 декабря 2010

Вы не можете скачать файл по запросу ajax. Заменить a4j:commandButton на h:commandButton.


Обновление в соответствии с обновлением вашего вопроса: чтобы заставить команды / ссылки внутри компонента UIData, такого как <h:dataTable>, <rich:dataTable> и т. Д. Работать, вам необходимо убедиться, что компонент, который содержит модель данных (что находится за атрибутом value компонента UIData) сохраняет точно такую ​​же модель данных во время запроса отправки формы. Если вы хотите, чтобы ваш запрос компонента был ограничен, то проще всего сослаться на компонент в теге <a4j:keepAlive>.

4 голосов
/ 25 декабря 2011
<h:commandButton id="getDownload" value="download"  action="#{controller.download()}"   >

</h:commandButton>
public class Controller {

OutputStream out = null;
String filename = "ali.pdf";
public void download() throws IOException {



    FacesContext fc = FacesContext.getCurrentInstance();
    HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
    out = response.getOutputStream();

    ZipOutputStream zipout = new ZipOutputStream(out);




    response.setContentType("application/octet-stream");
    response.addHeader("Content-Disposition", "attachment; filename=\""+filename+"\"");
    out.flush();







try {
        if (out != null) {
            out.close();
        }
        FacesContext.getCurrentInstance().responseComplete();
    } catch (IOException e) {

    }

}
...