8

HttpWebRequestオブジェクトを使用してリクエストを行う場合、GetResponse()メソッドを呼び出してリクエストを送信し、レスポンスを返す必要があります。
このメソッドの問題は、すべてのデータが受信されるまで応答オブジェクトを返さないことです。100 MBのファイルをダウンロードしているとすると、応答が終了して100MBがすべてダウンロードされるまでファイルを読み取ることができません。
私が欲しいのは、応答が完了するのを待たずに、応答ストリームのバイトが到着するとすぐに読み取れるようにすることです。
Range Httpヘッダーを使用できることはわかっていますが、私の状況では機能しません。

4

4 に答える 4

11

これは@Zacharyが提案するものに非常に近いと思います。そして、それは(そう思われる)機能します。using実際、@Zacharyのように使用する方が「より良い」と思います。
私の主なポイントは、GetResponse()あなたの(そう思われる)ブロッキング動作が説明できないことです。

さらに、次のコードは、すべてがどのように機能するかを大まかに示しています。たとえば、ストリームを最後まで読み取ることはありません(偶然の一致がない限り:))。ただし、VisualStudioの空の「コンソールアプリケーション」プロジェクトにコピーアンドペーストすると機能するはずです。

テストには「短い」URLを使用してみてください。ここでの例は、DebianディストリビューションのISO(600 Mバイトより少し多い)のダウンロードを開始します。申し訳ありませんが、Debian、私はあなたの帯域幅を盗むつもりはありませんでした。->ところで:そのようなシナリオをテストするために使用できる賢明なものはありますか?

このコードは、 C#(HTTPを介したXMLの連続ストリームの読み取り方法)に強く影響を受けています。

namespace StreamReadWebRequest
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.IO;

    class Program
    {
        static void Main(string[] args)
        {
            HttpWebRequest req;
            HttpWebResponse res = null;

            try
            {
                req = (HttpWebRequest)WebRequest.Create(
                        "http://cdimage.debian.org/debian-cd/5.0.4/i386/iso-cd/debian-504-i386-CD-1.iso");
                res = (HttpWebResponse)req.GetResponse();
                Stream stream = res.GetResponseStream();

                byte[] data = new byte[4096];
                int read;
                while ((read = stream.Read(data, 0, data.Length)) > 0)
                {
                    Process(data, read);
                }
            }
            finally
            {
                if (res != null)
                    res.Close();
            }
            Console.In.Read();
        }

        private static void Process(byte[] data, int read)
        {
            Console.Out.Write(ASCIIEncoding.ASCII.GetString(data));
        }
    }
}
于 2010-05-18T11:58:43.030 に答える
3

私は同じことを探していました。サーバーはチャンク化されたXMLデータをストリーミングし、サーバーのストリーミング中にこのデータにアクセスできるC#クライアントが必要でした。ソースにアクセスするためのさまざまな方法(WebChannelFactory、WebClient、HttpWebRequest / Response、TcpClient)を試しましたが、これまでのところ失敗しました。このスレッドを見つけると、次の行がブロックしているのと同じ問題が発生するHttpWebRequest/Responseに焦点を当てました。

HttpWebResponse resp = (HttpWebResponse)request.GetResponse();

Artiom Chilaruが述べたように、それがブロックしている場合:何かが間違っている。大きな.ISOファイルをダウンロードしてデフォルトの動作を再現しようとすることに焦点を当てているところ、FiddlerがGetResponse()メソッドをブロックしていることがわかりました。

ただし、ストリームが設定されたら(つまり、GetResponse()がすでに呼び出されている場合)、Fiddlerを開くのに問題はありませんが、HTTP GET中に、GetResponse()がブロックされている場合は、Fiddlerを閉じて、アプリケーションが継続しているかどうかを確認してください。これは通常のフローです(つまり、ストリームを読み取ります)。

于 2014-07-23T12:45:35.787 に答える
1

読み取りでバッファサイズを設定すると、データをチャンクで読み取ることができます...例...

 // Get the response stream
 using(Stream resStream = response.GetResponseStream())
 {

        string parseString = null;
        int    count      = 0;

        do
        {
            // Read a chunk of data
            count = resStream.Read(buf, 0, buf.Length);

            if (count != 0)
            {
                // Convert to ASCII
                parseString = Encoding.ASCII.GetString(buf, 0, count);

                // Append string to results
                sb.Append(tempString);
            }
        }
        while (count > 0);

}
于 2010-05-16T05:43:51.930 に答える
1

GetResponse()あなたがあなたの側に何を持っているかはわかりませんが、ファイル全体をダウンロードして戻さないという事実を知っています(そして多くの人がここで同意すると確信しています) 。リクエストを送信し、レスポンスを待ち、レスポンスヘッダーを取得します。

GetResponseStream()応答を取得したら、サーバーからダウンロードする実際のデータストリームである、を使用して応答ストリームを簡単に取得できます。また、ファイル全体をダウンロードする前に、応答ストリームに簡単にアクセスできます。これは100%真実であり、テスト済みです。

同じ動作が得られない場合(これは本当に奇妙で、発生しないはずです)、上記で説明したように機能しないコード例を追加できますか?

また、scherandによって投稿された例をテストしてください。特別なハックなしで、問題なく動作することをもう一度証明します。

于 2010-05-18T13:15:06.150 に答える