28

私は、人々がファイルをアップロードおよびダウンロードできるようにする小さなアプリケーションを作成しています。アップロード/ダウンロード機能を提供するために、このアプリケーションに Web サービスを追加しましたが、実装が大きなファイルにどれだけうまく対処できるかについてはよくわかりません。

現時点では、アップロードとダウンロードのメソッドの定義は次のようになっています (Apache CXF を使用して記述)。

boolean uploadFile(@WebParam(name = "username") String username,
    @WebParam(name = "password") String password,
    @WebParam(name = "filename") String filename,
    @WebParam(name = "fileContents") byte[] fileContents)
    throws UploadException, LoginException;

byte[] downloadFile(@WebParam(name = "username") String username,
    @WebParam(name = "password") String password,
    @WebParam(name = "filename") String filename) throws DownloadException,
    LoginException;

したがって、ファイルはバイト配列としてアップロードおよびダウンロードされます。しかし、ばかげたサイズ (たとえば 1GB) のファイルがある場合、確実にすべての情報をメモリに格納しようとし、サービスをクラッシュさせます。

だから私の質問は - 代わりにある種のストリームを返すことは可能ですか? ただし、これはOSにまったく依存しないものではないと思います。Web サービスの背後にある理論は知っていますが、実際的な側面については、まだ少し情報を収集する必要があります。

どんな意見でも乾杯、リー

4

12 に答える 12

14

はい、メトロで可能です。大きな添付ファイルの例を参照してください。

JAX-WS RI は、ストリーミング方式で大きな添付ファイルを送受信するためのサポートを提供します。

  • プログラミング モデルで MTOM と DataHandler を使用します。
  • DataHandler を StreamingDataHandler にキャストし、そのメソッドを使用します。
  • 必ず StreamingDataHandler.close() を呼び出し、StreamingDataHandler.readOnce() ストリームも閉じてください。
  • クライアント側で HTTP チャンクを有効にします。
于 2008-09-25T11:02:25.617 に答える
6

Stephen Denneは、あなたの要件を満たす Metro 実装を持っています。その理由を簡単に説明した後、私の答えを以下に示します。

HTTP をメッセージ プロトコルとして使用して構築されたほとんどの Web サービス実装は、単純な送受信パターンのみを許可するという点で REST に準拠しています。これにより、相互運用性が大幅に向上します。これは、さまざまなプラットフォームがすべてこの単純なアーキテクチャを理解できるためです (たとえば、.NET Web サービスと対話する Java Web サービス)。

これを維持したい場合は、チャンクを提供できます。

boolean uploadFile(String username, String password, String fileName, int currentChunk, int totalChunks, byte[] chunk);

これには、正しい順序でチャンクを取得できない場合 (または、チャンクを正しい順序で要求することもできます) に多少のフットワークが必要になりますが、おそらく実装は非常に簡単です。

于 2008-09-25T10:59:16.950 に答える
3

標準化されたWebサービスを使用する場合、送信者と受信者は、一方から他方に送信されるXMLデータの整合性に依存します。これは、最後のタグが送信されたときにのみWebサービスの要求と応答が完了することを意味します。これを念頭に置いて、Webサービスをストリームとして扱うことはできません。

標準化されたWebサービスはhttpプロトコルに依存しているため、これは論理的です。これは「ステートレス」であり、「接続を開く...リクエストを送信する...データを受信する...リクエストを閉じる」のように機能します。とにかく、接続は最後に閉じられます。したがって、ストリーミングのようなものはここで使用することを意図していません。または、httpより上にレイヤーします(Webサービスのように)。

申し訳ありませんが、私が見る限り、Webサービスでストリーミングする可能性はありません。さらに悪いことに、Webサービスの実装/構成によっては、byte []-データがCDATAタグではなくBase64に変換され、リクエストがさらに肥大化する可能性があります。

PS:うん、他の人が書いたように、「チュインキング」は可能です。しかし、これはそれ自体はストリーミングではありません;-)-とにかく、それはあなたを助けるかもしれません。

于 2008-09-25T11:05:41.693 に答える
1

ストリーミングWebサービスは不可能だと思っている人には、それを壊したくありませんが、実際には、すべてのhttpリクエストはストリームベースです。WebサイトへのGETを実行するすべてのブラウザは、ストリームベースです。Webサービスへのすべての呼び出しは、ストリームベースです。はい、すべてです。アーキテクチャの下位レベルがこれを処理しているため、サービスまたはページを実装しているレベルではこれに気づきませんが、実行されています。

ブラウザでページを取得するのに時間がかかる場合があることに気付いたことがありますか?ブラウザは砂時計を表示し続けますか?これは、ブラウザがストリームを待機しているためです。

ストリームは、mime / typesを実際のデータの前に送信する必要がある理由です。これはすべてブラウザへの単なるバイトストリームであり、最初に何であるかを伝えないと写真を識別できません。また、送信する前にバイナリのサイズを渡す必要があるのもそのためです。ブラウザは画像が停止した場所を認識できず、ページが再び表示されます。

それはすべて、クライアントへの単なるバイトのストリームです。これを自分で証明したい場合は、リクエストの処理の任意の時点で出力ストリームを取得し、それをclose()します。あなたはすべてを爆破します。ブラウザはすぐに砂時計の表示を停止し、「見つかりません」または「サーバーで接続がリセットされました」などのメッセージを表示します。

多くの人がこれらすべてがストリームベースであることを知らないということは、その上にどれだけのものが重ねられているかを示しています。あまりにも多くのことを言う人もいます-私はその一人です。

幸運と幸せな開発-それらの肩をリラックスさせてください!

于 2012-03-14T16:12:02.803 に答える
1

WCFの場合、メッセージのメンバーをストリームとして定義し、バインディングを適切に設定することが可能だと思います.Java Webサービスと通信するwcfでこの作業を見てきました。

httpTransport 構成で transferMode="StreamedResponse" を設定し、mtomMessageEncoding を使用する必要があります (構成でカスタム バインディング セクションを使用する必要があります)。

制限の 1 つは、ストリーミングしたい場合にメッセージ本文メンバーを 1 つしか持てないことだと思います (これは理にかなっています)。

于 2008-09-25T11:59:27.740 に答える
0

Webサービスリクエストは基本的に単一のHTTPPOSTに要約されることに注意してください。

.NETでの.ASMXファイルの出力を見ると、POSTリクエストとレスポンスがどのようになるかが正確にわかります。

@Guvanteが述べたように、チャンキングはあなたが望むものに最も近いものになるでしょう。

TCP / IPを処理し、アプリケーションにストリーミングするために独自のWebクライアントコードを実装できると思いますが、控えめに言ってもそれは複雑です。

于 2008-09-25T11:06:13.720 に答える
0

このタスクに単純なサーブレットを使用する方がはるかに簡単なアプローチだと思いますか、それともサーブレットを使用できない理由はありますか?

たとえば、Commonsオープンソースライブラリを使用できます。

于 2008-09-25T11:13:38.913 に答える
0

はい、Web サービスはストリーミングを実行できます。XML からの PDF ドキュメントのレンダリングをサポートするために、Apache Axis2 と MTOM を使用して Web サービスを作成しました。結果のファイルは非常に大きくなる可能性があるため、すべてをメモリに保持したくないため、ストリーミングが重要でした。SOAP 添付ファイルのストリーミングに関する Oracle のドキュメントを参照してください。

または、自分で行うこともできます。Tomcat は Chunked ヘッダーを作成します。これは、ストリーミングするスプリング コントローラー関数の例です。

 @RequestMapping(value = "/stream")
        public void hellostreamer(HttpServletRequest request, HttpServletResponse response) throws CopyStreamException, IOException  
{

            response.setContentType("text/xml");
            OutputStreamWriter writer = new OutputStreamWriter (response.getOutputStream());
            writer.write("this is streaming");
            writer.close();

    }
于 2011-08-08T15:39:23.240 に答える
0

これを行う 1 つの方法は、ファイルの一部をアップロードし、サーバーがそれをディスクに書き込むuploadFileChunk (byte[] chunkData, int size, int offset, int totalSize) メソッド (またはそのようなもの) を追加することです。

于 2008-09-25T11:02:25.523 に答える
0

Java 用のRMIIOライブラリーは、RMI 全体で RemoteInputStream を処理する機能を提供します。必要なのは RMI だけでしたが、他のタイプの RMI で動作するようにコードを適応させることができるはずです。これは、特にユーザー側で小さなアプリケーションを使用できる場合に役立ちます。ライブラリは、サーバーにプッシュされるデータのサイズを制限して、記述したタイプの状況を正確に回避できるようにするという明確な目的で開発されました。これは、RAM またはディスクをいっぱいにすることによる事実上の DOS 攻撃です。

RMIIO ライブラリを使用すると、サーバー側でプルするデータ量を決定できます。HTTP PUT および POST を使用すると、クライアントは、プッシュする速度を含めてその決定を下すことができます。

于 2008-09-25T11:59:14.810 に答える
0

実際、「TCP/IP を処理し、アプリケーションにストリーミングする」ことはそれほど難しくありません。これを試して...

class MyServlet extends HttpServlet
{
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    {
        response.getOutputStream().println("Hello World!");
    }
}

それだけです。上記のコードでは、ブラウザーから送信された HTTP GET 要求に応答し、そのブラウザーにテキスト "Hello World!" を返しています。

「Hello World!」に注意してください。は有効な HTML ではないため、ブラウザでエラーが発生する可能性がありますが、実際にはそれだけです。

あなたの開発に幸運を!

ロドニー

于 2012-04-02T19:02:16.930 に答える