سؤال

أواجه مشكلة في قراءة استجابة "مقطعة" عند استخدام StreamReader لقراءة الدفق الذي تم إرجاعه بواسطة GetResponseStream() لـ HttpWebResponse:

// response is an HttpWebResponse
StreamReader reader = new StreamReader(response.GetResponseStream());
string output = reader.ReadToEnd(); // throws exception...

عندما reader.ReadToEnd() الطريقة تسمى أحصل على System.IO.IOException التالي: غير قادر على قراءة البيانات من اتصال النقل:تم إغلاق الاتصال.

يعمل الكود أعلاه بشكل جيد عندما يقوم الخادم بإرجاع استجابة "غير مقسمة".

الطريقة الوحيدة التي تمكنت من تشغيلها هي استخدام HTTP/1.0 للطلب الأولي (بدلاً من HTTP/1.1، الافتراضي) ولكن هذا يبدو وكأنه حل بديل ضعيف.

أيه أفكار؟


@ تشاك

الحل الخاص بك يعمل بشكل جيد.لا يزال يطرح نفس IOException في القراءة الأخيرة ().ولكن بعد فحص محتويات StringBuilder يبدو أنه تم استلام جميع البيانات.لذلك ربما أحتاج فقط إلى تغليف القراءة () في محاولة الالتقاط وابتلاع "الخطأ".

هل كانت مفيدة؟

المحلول

لم تجرب هذا من خلال استجابة "مقطعة" ولكن هل سيعمل شيء مثل هذا؟

StringBuilder sb = new StringBuilder();
Byte[] buf = new byte[8192];
Stream resStream = response.GetResponseStream();
string tmpString = null;
int count = 0;
do
{
     count = resStream.Read(buf, 0, buf.Length);
     if(count != 0)
     {
          tmpString = Encoding.ASCII.GetString(buf, 0, count);
          sb.Append(tmpString);
     }
}while (count > 0);

نصائح أخرى

أنا أعمل على مشكلة مماثلة.يتعامل كل من .net HttpWebRequest وHttpWebRequest مع ملفات تعريف الارتباط وعمليات إعادة التوجيه تلقائيًا، لكنهما لا يتعاملان مع المحتوى المقسم في نص الاستجابة تلقائيًا.

ربما يرجع السبب في ذلك إلى أن المحتوى المقسم قد يحتوي على أكثر من مجرد بيانات بسيطة (على سبيل المثال:أسماء القطع، الرؤوس اللاحقة).

إن مجرد قراءة الدفق وتجاهل استثناء EOF لن يعمل لأن الدفق يحتوي على أكثر من المحتوى المطلوب.سيحتوي الدفق على أجزاء وتبدأ كل قطعة بالإعلان عن حجمها.إذا تمت قراءة الدفق ببساطة من البداية إلى النهاية، فستحتوي البيانات النهائية على البيانات التعريفية للقطعة (وفي حالة محتوى gzip، فسوف تفشل في التحقق من CRC عند فك الضغط).

لحل المشكلة، من الضروري تحليل التدفق يدويًا، وإزالة حجم القطعة من كل قطعة (بالإضافة إلى محددات CR LF)، والكشف عن القطعة النهائية والاحتفاظ ببيانات القطعة فقط.من المحتمل أن تكون هناك مكتبة في مكان ما تقوم بذلك، ولم أجدها بعد.

موارد مفيدة:

http://en.wikipedia.org/wiki/Chunked_transfer_encoding http://tools.ietf.org/html/rfc2616#section-3.6.1

كريج، بدون رؤية الدفق الذي تقرأه، يكون من الصعب تصحيح الأخطاء ولكن ربما يمكنك تغيير إعداد متغير العدد إلى هذا:

count = resStream.Read(buf, 0, buf.Length-1);

إنه نوع من الاختراق، ولكن إذا كانت القراءة الأخيرة تقتلك ولم تُرجع أي بيانات، فمن الناحية النظرية فإن هذا سوف يتجنب المشكلة.ما زلت أتساءل لماذا يفعل الدفق ذلك.

لقد واجهت نفس المشكلة (وهكذا انتهى بي الأمر هنا :-).في النهاية تم تتبعه وصولاً إلى حقيقة أن الدفق المقسم لم يكن صالحًا - الجزء الأخير ذو الطول الصفري كان مفقودًا.لقد توصلت إلى الكود التالي الذي يتعامل مع التدفقات المقسمة الصالحة وغير الصالحة.

using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
    StringBuilder sb = new StringBuilder();

    try
    {
        while (!sr.EndOfStream)
        {
            sb.Append((char)sr.Read());
        }
    }
    catch (System.IO.IOException)
    { }

    string content = sb.ToString();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top