Weird EOF Exception while trying to download file from GWT application
Test Scenarios:
Scenario 1 If I hit url of servlet directly, it always give me desired result without any problems.Scenario 2 Using GWT client on IE8,I am able to download file without any code changes. However on some other computer as soon as I try to write file content on response output stream, I get EOF exception.
org.mortbay.jetty.EofException
at org.mortbay.jetty.HttpGenerator.flush(HttpGenerator.java:760) at org.mortbay.jetty.AbstractGenerator$Output.flush(AbstractGenerator.java:566) at org.mortbay.jetty.HttpConnection$Output.flush(HttpConnection.java:911) at java.io.BufferedOutputStream.flush(Unknown Source) atXXXXXXXXXXXXXXX开发者_运维问答XXXXXXXXXXXXXXXXXXXXX.doGet(ServiceDataExporterServlet.java:110) at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)Creating input stream....Code of servlet is as follows:
try
{ output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE); byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; int length; int bytesWritten=0; while ((length = data.read(buffer)) > 0) { bytesWritten+=length; output.write(buffer, 0, length); } output.flush() // At this point I am facing EOF exception. where data is inputStream Via means of bytesWritten variable I have confirmed that in all the three scenarios content has been written in the same way in output stream. But not sure why it is not working in some computers. Any points will be highly appereciated.I do something like this to download files with GWT
In the server side:
public static void sendFileToClient(String path, String filename,
int contentLen, HttpServletRequest request,
HttpServletResponse response) throws UnsupportedEncodingException
{
String ua = request.getHeader("User-Agent").toLowerCase();
boolean isIE = ((ua.indexOf("msie 6.0") != -1) || (ua
.indexOf("msie 7.0") != -1)) ? true : false;
String encName = URLEncoder.encode(filename, "UTF-8");
// Derived from Squirrel Mail and from
// http://www.jspwiki.org/wiki/BugSSLAndIENoCacheBug
if (request.isSecure())
{
response.addHeader("Pragma", "no-cache");
response.addHeader("Expires", "-1");
response.addHeader("Cache-Control", "no-cache");
}
else
{
response.addHeader("Cache-Control", "private");
response.addHeader("Pragma", "public");
}
if (isIE)
{
response.addHeader("Content-Disposition", "attachment; filename=\"" + encName + "\"");
response.addHeader("Connection", "close");
response.setContentType("application/force-download; name=\"" + encName + "\"");
}
else
{
response.addHeader("Content-Disposition", "attachment; filename=\""
+ encName + "\"");
response.setContentType("application/octet-stream; name=\""
+ encName + "\"");
if (contentLen > 0)
response.setContentLength(contentLen);
}
try
{
FileInputStream zipIn = new FileInputStream(new File(path));
ServletOutputStream out = response.getOutputStream();
response.setBufferSize(8 * 1024);
int bufSize = response.getBufferSize();
byte[] buffer = new byte[bufSize];
BufferedInputStream bis = new BufferedInputStream(zipIn, bufSize);
int count;
while ((count = bis.read(buffer, 0, bufSize)) != -1)
{
out.write(buffer, 0, count);
}
bis.close();
zipIn.close();
out.flush();
out.close();
}
catch (FileNotFoundException e)
{
System.out.println("File not found");
}
catch (IOException e)
{
System.out.println("IO error");
}
}
I have a servlet that expects for an id and then I get the related file path and I serve it to the browser with the above code.
In the client side:
public class DownloadIFrame extends Frame implements LoadHandler,
HasLoadHandlers
{
public static final String DOWNLOAD_FRAME = "__gwt_downloadFrame";
public DownloadIFrame(String url)
{
super();
setSize("0px", "0px");
setVisible(false);
RootPanel rp = RootPanel.get(DOWNLOAD_FRAME);
if (rp != null)
{
addLoadHandler(this);
rp.add(this);
setUrl(url);
}
else
openURLInNewWindow(url);
}
native void openURLInNewWindow(String url) /*-{
$wnd.open(url);
}-*/;
public HandlerRegistration addLoadHandler(LoadHandler handler)
{
return addHandler(handler, LoadEvent.getType());
}
public void onLoad(LoadEvent event)
{
}
}
In you hosted page add this Iframe
<iframe src="javascript:''" id="__gwt_downloadFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
Then to download a file put something like this:
btnDownload.addClickHandler(new ClickHandler()
{
public void onClick(ClickEvent arg0)
{
String url = GWT.getModuleBaseURL()
+ "/downloadServlet?id=[FILE_ID]";
new DownloadIFrame(url);
}
});
I hope this helps you.
Happy coding!
It happens also if the OutputStream flushes after InputStream was closed, like this:
myInputStream.close();
myOutputStream.flush();
myOutputStream.close();
it should be like:
myOutputStream.flush();
myInputStream.close();
myOutputStream.close();
Hope it helps :-)
精彩评论