Ich schreibe ein GWT-Service-Servlet, Instanz von RemoteServiceServlet, und gegeben die DateiID vom Client, das Ziel ist es, Datei von DB zu holen und es auf den Client zu schieben. Das Servlet gibt eine Fehlermeldung als String-Objekt zurück.Datei mit GWT RemoteServiceServlet herunterladen
Was mache ich falsch?
Ich recherchiere das im Netz und einige Leute behaupten, dass es nicht vom RemoteServiceServlet getan werden kann ?!
In meinem Fall muss der Server zuerst eine Datei aus der Datenbank holen, dann kann er sie an den Client senden, also muss ich ihn zuerst vorbereiten. Gibt es eine Möglichkeit, einen Download auf den Client zu "pushen", oder muss ich ein dediziertes Servlet nur für den Download schreiben? Kann jemand mir einen Beispielcode geben, wie man das macht?
Danke!
Dies ist der Code, den ich bisher haben und die Ausnahme erzeugt sie:
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;
}
}
Server erzeugt eine Ausnahme:
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
Haben Sie versucht, die Datei direkt auszulesen und dann Ihr Servlet zu testen? Vielleicht dauert Ihr Datenbankzugriff zu lange? In einer Anwendung (ich weiß) wird die Datei zuerst in ein Byte-Array gestellt und dann out.write, out.flush und out.close aufgerufen. Und es funktioniert. Ich kann auch Mockrunner (für Servlets) zum Testen empfehlen, funktioniert super mit GWT. – Akkusativobjekt
Werfen Sie einen Blick auf [diese Frage] (http://stackoverflow.com/questions/2822667/download-dynamic-file-with-gwt). Sie können keine Stream-Binärdaten von einem RPC-Aufruf zurückgeben. Dies muss über ein Standard-Servlet erfolgen. – Baz
Danke Baz, das führte mich zu einer Lösung :) über die Rückgabe eines Dateinamens, und Client-Seite ein dediziertes Download-Servlet aufrufen. Vielen Dank! – Marcin