The file is extracted from a database and does not exist on the server's filesystem yet; redirecting to a servlet to create and send the response which contains the file to download fails with a generic:
java.lang.IllegalStateException: Can't invoke sendRedirect() after certain methods have been called
More specifically, that method can not be invoked after any of the following methods of the ActionResponse interface has been called:
- setPortletMode
- setWindowState
- setRenderParameter
- setRenderParameters
- removePublicRenderParamter
However there's a working yet nasty workaround. It's bad and you should feel bad, but it works.. ish
Temporarily create the file placing it inside the portal directory where the portlet WAR has been unpacked, then link directly to it, remembering to delete it after some time. This can all be achieved from directly inside a JSP:
[...]
<%
/*before landing on the JSP the attachments where recovered as Blobs from the DB and stored in a session attribute called "attachments"
we now recover it*/
List attachments = (List)results.getAttribute("attachments");
if(attachments!=null){//important to avoid NullPointerExceptions!!
Iterator iter = attachments.iterator();
//for each attachment present a link to download it
while(iter.hasNext()){
Blob b = (Blob)iter.next();
//check if it's not just and empty blob
if(b!=null){
InputStream is = b.getBinaryStream();
File myWar = null;
try{
/*each deployed portlet will be assigned an unique name which does not change on subsequent deploys. Once you find the full path
to the portlet's folder you should put it here.
The path should be something like:
/opt/WebSphere/PortalServer/installedApps/PORTLET_NAME_RANDOM_STRING.ear/SAME_RANDOM_STRING.war
and you may want to add a /resources at the end to keep things a little tidier
*/
myWar = new File("YOUR_PATH");
if(!myWar.exists()){
myWar.mkdir();
}
}
catch(Exception e){
//do something
}
File f = null;
try{
//create temp file to be downloaded
f= File.createTempFile("SOME_NAME", "SOME_EXTENSION", myWar);
}catch(Exception e){
//do something
}
//write the blob to the temp file
FileOutputStream fos = new FileOutputStream(f.getAbsolutePath());
int read = 0;
byte[] bytes = new byte[1024];
while ((read = is.read(bytes)) != -1) {
fos.write(bytes, 0, read);
}
fos.close();
String folder = "/resources/"+f.getName();
//finally output the link to download the file
%>
<a target="_blank" href="<c:url value="<%=folder%>" />">"Download your file"</a>
<%
}
}
}
%>
[...]
Of course, suggestions for more practical and clean solutions are well accepted.
No comments:
Post a Comment
With great power comes great responsibility