This is what I'm doing. YMMV and assorted disclaimers; it's quite
likely that this can be improved upon.
(1) I generate this place-holder for the file download in my GWT web
pages:
out.println("<div id=\"__gwt_downloadFrame\" tabIndex='-1'></
div>");
(2) To initiate a download from the client side, I do this:
public static void download(String p_uuid, String p_filename)
{
String fileDownloadURL = "/fileDownloadServlet"
+ "?id=" + p_uuid
+ "&filename=" +
URL.encode(p_filename);
Frame fileDownloadFrame = new Frame(fileDownloadURL);
fileDownloadFrame.setSize("0px", "0px");
fileDownloadFrame.setVisible(false);
RootPanel panel = RootPanel.get("__gwt_downloadFrame");
while (panel.getWidgetCount() > 0)
panel.remove(0);
panel.add(fileDownloadFrame);
}
(3) The corresponding FileDownloadServlet does this (with unimportant
details omitted):
@Override
protected void doGet(HttpServletRequest p_request,
HttpServletResponse p_response)
throws ServletException, IOException
{
String filename = p_request.getParameter("filename");
if (filename == null)
{
p_response.sendError(SC_BAD_REQUEST, "Missing filename");
return;
}
File file = /* however you choose to go about resolving
filename */
long length = file.length();
FileInputStream fis = new FileInputStream(file);
p_response.addHeader("Content-Disposition",
"attachment; filename=\"" + filename +
"\"");
p_response.setContentType("application/octet-stream");
if (length > 0 && length <= Integer.MAX_VALUE);
p_response.setContentLength((int)length);
ServletOutputStream out = p_response.getOutputStream();
p_response.setBufferSize(32768);
int bufSize = p_response.getBufferSize();
byte[] buffer = new byte[bufSize];
BufferedInputStream bis = new BufferedInputStream(fis,
bufSize);
int bytes;
while ((bytes = bis.read(buffer, 0, bufSize)) >= 0)
out.write(buffer, 0, bytes);
bis.close();
fis.close();
out.flush();
out.close();
}
That all causes the selected file to be downloaded to the client
browser in whatever way the browser chooses to handle downloads.