2016-03-28 5 views
0

私はGWTサービスサーブレット(RemoteServiceServletのインスタンス)を作成しており、クライアントからfileIDが与えられているので、DBからファイルを取得してクライアントにプッシュすることが目的です。サーブレットは、エラー・メッセージをStringオブジェクトとして戻します。GWTでファイルをダウンロードするRemoteServiceServlet

私は間違っていますか?

私はこれをネット上で研究していますが、RemoteServiceServletから実行できないと主張する人もいます。

私の場合、サーバーはまずデータベースからファイルをフェッチしてからクライアントに送信する必要があるため、最初に準備する必要があります。ダウンロードをクライアントに「プッシュ」する方法はありますか、ダウンロード専用のサーブレットを作成する必要はありますか?誰かが私に例コードを与える方法はありますか?

ありがとうございます!

これは私がこれまで持っているコードと、それが生成する例外です:

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

ファイルを直接読み込み、サーブレットをテストしようとしましたか?たぶんあなたのデータベースへのアクセスに時間がかかりますか?アプリケーションでは(私は知っている)、ファイルはまずバイト配列に入れられ、その後out.write、out.flush、out.closeが呼び出されます。そして、それは動作します。また、テスト用のMockrunner(サーブレット用)をお勧めします.GWTでうまく動作します。 – Akkusativobjekt

+1

[この質問](http://stackoverflow.com/questions/2822667/download-dynamic-file-with-gwt)をご覧ください。 RPC呼び出しからのストリームバイナリデータを返すことはできません。標準のサーブレットから実行する必要があります。 – Baz

+0

が、これは、専用のダウンロードサーブレットを呼び出して、ファイル名を返す経由ソリューション:)、およびクライアント側に私を導く、あなたのバズをありがとうございます。ありがとう! – Marcin

答えて

0

私はあなたがバイナリデータファイルをストリーミングすることができないというSripathiクリシュナンから出ましたRPC呼び出しで - このポストを参照してくださいhttps://stackoverflow.com/a/2823184/1431879

解決策は、SSRからの提案に従うことでした。ダウンロードサーブレット - このポストを参照してくださいhttps://stackoverflow.com/a/13739960/1431879

これにより、ブラウザによってブロックされたポップアップが作成されました。しかし、サーバ上でファイルを準備してURLを準備しておくと、RPCはファイル名を返し、クライアントはそれを使って専用のサーブレットから直接ダウンロードを要求します。ダウンロード用のiframeを作成しました。私は、ユーザーが ファイルを生成されたサーブレットをダウンロードできる場所の数を持っている

:私はここhttp://grokbase.com/p/gg/google-web-toolkit/13264b94q6/how-to-download-a-file-from-server-without-browser-opening-new-window

ここでは彼のポストからの直接の引用であることを行う方法サドにより、優れた記事を見つけました。私は私のアプリのHTMLでは、いくつかのステップ

1)と一般的にこれを扱う、私は私のアプリのエントリーポイントで)IFRAMEに

2を入れて、私は "=

プライベート静的最終文字列DOWNLOAD_IFRAMEを宣言します__gwt_downloadFrame "; プライベート静的フレームdownloadFrame; ...

ラップIFRAME:

@Override公共ボイドonModuleLoad(){ downloadFrame = Frame.wrap(Document.get()getElementByIdを(DOWNLOAD_IFRAME))。 ...

公共の静的な無効downloadURL(文字列のURL){ downloadFrameをダウンロードするための方法を提供します。setUrl(url);ダウンロードの準備ができているときはいつでも}

3) は、RPCコール

MyApp.downloadURL(URL)の()するonSuccessに言います。

関連する問題