質問

私は人々が私にファイルをアップロードしたりダウンロードしたりできる小さなアプリケーションを書いています。このアプリケーションにアップロード/ダウンロード機能を提供する 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 サービスの背後にある理論は知っていますが、実際的な側面については、まだ少し情報を得る必要があります。

あらゆる入力を乾杯、リー

役に立ちましたか?

解決

スティーブン・デン 要件を満たす Metro 実装があります。なぜそうなるのかについて簡単に説明した後、私の答えを以下に示します。

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

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

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

これは、チャンクを正しい順序で取得できない場合 (または、チャンクが正しい順序で来るように要求することもできます) 場合には、ある程度の労力を必要としますが、おそらく実装は非常に簡単でしょう。

他のヒント

はい、メトロなら可能です。を参照してください。 大型アタッチメント たとえば、これはあなたが望むことを行うように見えます。

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

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

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

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

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

追記:はい、他の人が書いているように、「チャンキング」は可能です。しかし、これはストリーミングそのものではありません ;-) - とにかく、役に立つかもしれません。

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

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

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

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

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

幸運と幸せな発展を祈ります - 肩の力を抜いてください!

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

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

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

アパッチCXF ストリームの送受信をサポートします。

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

Web サービス リクエストは基本的に 1 つの HTTP POST に集約されることに注意してください。

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

@Guvante が言及したように、チャンク化は、希望するものに最も近いものになります。

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

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

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

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

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

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

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

 @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();

    }

「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ではないので、ブラウザにエラーが発生する可能性がありますが、それは本当にすべてです。

あなたの発展に幸あれ!

ロドニー

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top