My solution to binary downloads from within webflow. It's essentially the same solution proposed by JamesClinton in http://forum.springframework.org/showthread.php?t=52454
webmvc-config.xml:
Code:
<!-- URL to flow mapping rules -->
<bean id="flowUrlMappings" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/flow/*=flowController
/download=defaultController
</value>
</property>
<property name="order" value="0"/>
</bean>
<!--
- This is a MultiActionController that manages simple view rendering where backend services
- are invoked but there is no need for form binding or a FormController
-->
<bean id="defaultController" class="com.mydomain.myapp.common.web.MyMultiActionController">
<property name="methodNameResolver">
<bean class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/download">downloadHandler</prop>
</props>
</property>
</bean>
</property>
</bean>
reprintReport-flow.xml:
Code:
<view-state id="confirmReprint" view="reprintReportView">
<transition on="reprintReportEvent" to="downloadReport">
<evaluate expression="reportWeb.fetchReportPdf(reportId, externalContext)" />
</transition>
<transition on="cancel" to="finish" />
</view-state>
<view-state id="downloadReport" view="externalRedirect:/download">
<transition to="finish" />
</view-state>
<end-state id="finish"/>
reportWeb.java:
Code:
public void fetchReportPdf(int reportId, ExternalContext externalContext) {
String fileName = "Report-" + reportId + ".pdf";
OutputStream reportPdfOutput = reportService.fetchReportPdf(reportId);
externalContext.getSessionMap().put("fileName",fileName);
externalContext.getSessionMap().put("pdf", reportPdfOutput);
}
MyMultiActionController.java:
Code:
public class MyMultiActionController extends org.springframework.web.servlet.mvc.multiaction.MultiActionController {
.
.
.
public void downloadHandler(HttpServletRequest request, HttpServletResponse response) {
String fileName = (String) request.getSession().getAttribute("fileName");
OutputStream pdfOutput = (OutputStream) request.getSession().getAttribute("pdf");
if (null != pdfOutput) {
PdfUtil.flushOutputToResponse(response, fileName, pdfOutput);
}
}
If the user cancels the "Do you want to open or save this file?" dialog that Internet Explorer displays, an exception appears in the log. However, this doesn't seem to affect the flow execution.
Code:
java.lang.IllegalStateException: SRVE0199E: OutputStream already obtained
If the user opens or saves the PDF download, no exception appears in the log.