Как скачать динамически сгенерированный файл XML в JSF?

1

На странице JSF у меня есть:

<p:commandButton value="Download" action="#{myMBean.downloadXMLFile}" />

В MBean у меня есть следующее (try/catch ommited):

public void downloadXMLFile() {

String xml = this.getXML();//returns the whole XML but in String format.
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();  
response.setContentType("text/xml");
response.setHeader("Content-Disposition", "attachment;filename=file.xml");  

ServletOutputStream out = response.getOutputStream();
out.write(xml.getBytes());  
out.flush(); 
}

Но когда я запускаю его, я получаю исключение IllegalStateException:

java.lang.IllegalStateException: setBufferSize() called after first write to Output Stream/Writer

Я также попытался преобразовать XML-строку в документ и преобразовать ее в файл, но получил ту же ошибку. действительно ли это необходимо для того, чтобы работать?

  • 0
    Вы уже начали запись в поток, но фаза рендеринга JSF не знает, что ваш ответ завершен, поэтому он пытается его отрендерить и завершается неудачно. Поскольку вы используете ExternalContext вы должны вызвать responseComplete() в вашем экземпляре FacesContext чтобы избежать этого.
Теги:
jsf
download

1 ответ

2
Лучший ответ

Ошибка возникает из-за попытки отобразить ваш ответ во время фазы рендеринга JSF.

Вы используете исходный объект ответа, полученный через ExternalContext, и сами пишите ответ. Вы должны указать время выполнения JSF, что ответ завершен, поэтому он не пытается его обработать.

Сохраните ссылку на свой FacesContext:

FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) ctx.getExternalContext().getResponse();
...

и вызовите responseComplete() когда вы закончите создание своего ответа:

ctx.responseComplete();
  • 0
    Спасибо, это сработало! Как примечание, мне также пришлось изменить страницу: с <p: commandButton> на <h: commandButton>
  • 0
    Вы можете добавить ajax="false" чтобы отключить любую обработку ajax по умолчанию.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню