I have a form with two rich text fields used to hold attachments and an XPage that contains two file download controls (one for each field) and two buttons.
The buttons call a method in a Java class that creates a zip file containing the files from the relevant field. The zip file is downloaded in the browser for the user.
It all works perfectly - apart from the fact that if you download either zip file, you cannot immediately download the other. There is a delay of around 15-20 seconds before the second button click does anything.
XPage :-
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Document"></xp:dominoDocument>
</xp:this.data>
<xp:panel tagName="div"
style="margin-left:auto; margin-right:auto; width:50%">
<xp:br></xp:br>
<xp:fileDownload rows="30" id="fileDownload1"
displayLastModified="false" value="#{document1.Body1}">
</xp:fileDownload>
<xp:button value="Download Zipfile 1" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.script><![CDATA[console.log("Button1 click")]]></xp:this.script>
<xp:this.action><![CDATA[#{javascript:uk.co.mp.DownloadAllAttachments.downloadFromField(context.getUrlParameter("documentId"), "Body1");
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:br></xp:br>
<xp:fileDownload rows="30" id="fileDownload2"
displayLastModified="false" value="#{document1.Body2}">
</xp:fileDownload>
<xp:button value="Download Zipfile 2" id="button2">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.script><![CDATA[console.log("Button2 click")]]></xp:this.script>
<xp:this.action><![CDATA[#{javascript:uk.co.mp.DownloadAllAttachments.downloadFromField(context.getUrlParameter("documentId"), "Body2");
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:view>
Java class :-
package uk.co.mp;
import java.io.BufferedInputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;
import lotus.domino.Document;
import lotus.domino.EmbeddedObject;
import lotus.domino.RichTextItem;
import com.ibm.xsp.designer.context.XSPContext;
import com.ibm.xsp.model.domino.DominoUtils;
//
import lotus.domino.Session;
import lotus.domino.Database;
import com.ibm.xsp.extlib.util.ExtLibUtil;
public class DownloadAllAttachments {
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void downloadFromField(String documentUNID, String fieldName) {
// Initialize global XPage objects
FacesContext facesContext = FacesContext.getCurrentInstance();
XSPContext context = XSPContext.getXSPContext(facesContext);
UIViewRoot view = facesContext.getViewRoot();
Map viewScope = view.getViewMap();
try {
if (documentUNID == null || documentUNID.trim().equals("")) {
viewScope.put("errorString", "URL parameter \"documentUNID\" or \"u\" is required.");
view.setRendered(true);
return;
}
Session s = ExtLibUtil.getCurrentSessionAsSigner();
Database db = s.getCurrentDatabase();
// Get and validate the document from which attachments would be zipped
Document downloadDocument = null;
downloadDocument = db.getDocumentByUNID(documentUNID);
// Get and validate zip file name from URL
String zipFileName = fieldName + ".zip";
boolean bAnyAttachments = false;
EmbeddedObject embeddedObj = null;
Vector attachments = null;
// ...check for attachments in the field supplied and collect the names of the attachments
RichTextItem rtitem = (RichTextItem)downloadDocument.getFirstItem(fieldName);
Vector vec = rtitem.getEmbeddedObjects();
attachments = new Vector(vec.size());
if (!vec.isEmpty()) {
Iterator it = vec.iterator();
while(it.hasNext()){
embeddedObj = (EmbeddedObject)it.next();
if (embeddedObj != null) {
attachments.add(embeddedObj.getName());
bAnyAttachments = true;
}
}
}
//By this point we should have a list of the attachment names we want to include in the zip file
//If we have not found any attachments then return a message
if (!bAnyAttachments) {
viewScope.put("errorString", "<center><h3>No attachments found in the Document.</h3></center>");
return;
}
// Set response header values
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", -1);
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=" + zipFileName);
// Get stream related objects
OutputStream outStream = response.getOutputStream();
ZipOutputStream zipOutStream = new ZipOutputStream(outStream);
BufferedInputStream bufferInStream = null;
// Get all attachment names and loop through all of them adding to zip
for (int i = 0; i < attachments.size(); i++) {
embeddedObj = downloadDocument.getAttachment(attachments.get(i).toString());
if (embeddedObj != null) {
bufferInStream = new BufferedInputStream(embeddedObj.getInputStream());
int bufferLength = bufferInStream.available();
byte data[] = new byte[bufferLength];
bufferInStream.read(data, 0, bufferLength); // Read the attachment data
ZipEntry entry = new ZipEntry(embeddedObj.getName());
zipOutStream.putNextEntry(entry);
zipOutStream.write(data); // Write attachment into Zip file
bufferInStream.close();
embeddedObj.recycle();
}
}
// Clean up and close objects
downloadDocument.recycle();
zipOutStream.flush();
zipOutStream.close();
outStream.flush();
outStream.close();
facesContext.responseComplete();
} catch (Exception e) {
viewScope.put("errorString", "Error while zipping attachments.<br>" + e.toString());
e.printStackTrace();
}
}
}
Is there something preventing the second button click from occurring for that 15-20 seconds? Many thanks for any suggestions
Try adding XSP.allowSubmit()
to the client side JS event of your button.
<xp:button value="Download Zipfile 1" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.script><![CDATA[console.log("Button1 click")]]></xp:this.script>
<xp:this.action><![CDATA[#{javascript:uk.co.mp.DownloadAllAttachments.downloadFromField(context.getUrlParameter("documentId"), "Body1");
}]]></xp:this.action>
<xp:this.script><![CDATA[XSP.allowSubmit()]]></xp:this.script>
</xp:eventHandler>
</xp:button>