我正在编写一个GWT服务servlet,RemoteServiceServlet的实例,并且客户端给出了fileID,目标是从DB获取文件并将其推送到客户端。 servlet将任何错误消息作为String对象返回。
我做错了什么?
我正在网上研究这个,有些人声称无法通过RemoteServiceServlet完成这项工作?!
在我的情况下,服务器必须首先从数据库中获取文件,然后它可以将其发送到客户端,所以我必须先准备它。有没有办法将下载“推”到客户端,或者我是否必须编写专用的servlet才能下载?有人可以给我一个示例代码怎么做?
谢谢!
这是我到目前为止的代码以及它生成的异常:
public class MyServiceImpl extends RemoteServiceServlet implements MyService {
@Override
public String getFile(Long fileId) {
String errors = null;
File file = fetchFileByID(fileId);
try {
if (file != null && file.exists()) {
String name = fileLink.getName();
HttpServletResponse response = getThreadLocalResponse();
long fileLen = file.length();
if (fileLen > Integer.MAX_VALUE)
throw new IllegalStateException("File too large, cannot download using the browser.");
int length = (int) fileLen;
// do not cache
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
// content length is needed for MSIE
response.setContentLength(length);
response.setHeader("Content-Type", "application/octet-stream;");
response.setHeader("Content-Disposition", "attachment;filename=\"" + name + "\"");
OutputStream os = response.getOutputStream();
FileInputStream is = new FileInputStream(file);
BufferedInputStream buf = new BufferedInputStream(is);
int readBytes=0;
while((readBytes=buf.read())!=-1) {
os.write(readBytes);
}
os.flush();
buf.close();
} else {
errors = "File not found.";
}
} catch (IOException e) {
errors = e.getMessage();
} finally {
if (file != null)
file.delete();
}
return errors;
}
}
服务器生成异常:
Starting Jetty on port 8888
[WARN] /saluweb/SaluService
java.lang.RuntimeException: Unable to report failure
at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doUnexpectedFailure(AbstractRemoteServiceServlet.java:107)
at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:67)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:686)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:501)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.handler.RequestLogHandler.handle(RequestLogHandler.java:68)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:370)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:960)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1021)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:668)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: Closed
at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:140)
at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:117)
at com.google.gwt.user.server.rpc.RPCServletUtils.writeResponse(RPCServletUtils.java:375)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.writeResponse(RemoteServiceServlet.java:460)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:313)
at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
... 27 more
答案 0 :(得分:0)
我从Sripathi Krishnan发现你无法在RPC调用中传输二进制数据文件 - 请参阅这篇文章https://stackoverflow.com/a/2823184/1431879
解决方案是遵循SSR的建议并实施下载Servlet - 请参阅此帖https://stackoverflow.com/a/13739960/1431879
然而,这创建了一个被浏览器阻止的弹出窗口。但是在服务器和已准备好的URL上准备好文件后,我的RPC返回文件名,客户端使用它来请求从专用servlet直接下载。我为下载创建了一个iframe。我在Thad找到了一篇优秀的帖子http://grokbase.com/p/gg/google-web-toolkit/13264b94q6/how-to-download-a-file-from-server-without-browser-opening-new-window
以下是他的帖子的直接引用:
我有很多地方可以让用户下载生成的servlet 文件。我通过几个步骤来处理这个问题
1)在我的应用程序的HTML中,我放了一个IFRAME
2)在我的应用程序的EntryPoint中,我声明了
private static final String DOWNLOAD_IFRAME =“__ gwt_downloadFrame”; private static Frame downloadFrame; ...
包装IFRAME:
@覆盖 public void onModuleLoad(){ downloadFrame = Frame.wrap(Document.get()的getElementById(DOWNLOAD_IFRAME)。); ...
提供下载方法
public static void downloadURL(String url){ downloadFrame.setUrl(URL); }
3)每当下载准备就绪时,请参考RPC调用的onSuccess()
MyApp.downloadURL(URL);