سؤال

أريد الحصول على حجم ملف http://.../ قبل تنزيله.يمكن أن يكون الملف صفحة ويب أو صورة أو ملف وسائط.هل يمكن القيام بذلك باستخدام رؤوس HTTP؟كيف أقوم بتنزيل رأس ملف HTTP فقط؟

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

المحلول

نعم، بافتراض أن خادم HTTP الذي تتحدث إليه يدعم/يسمح بذلك:

public long GetFileSize(string url)
{
    long result = -1;

    System.Net.WebRequest req = System.Net.WebRequest.Create(url);
    req.Method = "HEAD";
    using (System.Net.WebResponse resp = req.GetResponse())
    {
        if (long.TryParse(resp.Headers.Get("Content-Length"), out long ContentLength))
        {
            result = ContentLength;
        }
    }

    return result;
}

إذا كان استخدام أسلوب HEAD غير مسموح به، أو كان رأس Content-Length غير موجود في رد الخادم، فإن الطريقة الوحيدة لتحديد حجم المحتوى على الخادم هي تنزيله.نظرًا لأن هذا ليس موثوقًا بشكل خاص، فإن معظم الخوادم ستتضمن هذه المعلومات.

نصائح أخرى

هل يمكن القيام بذلك باستخدام رؤوس HTTP؟

نعم، هذا هو الطريق للذهاب. لو يتم توفير المعلومات، وهي موجودة في الرأس باسم Content-Length.ومع ذلك، لاحظ أن هذا ليس هو الحال بالضرورة.

يمكن تنزيل الرأس فقط باستخدام ملف HEAD طلب بدلا من GET.ربما يساعد الكود التالي:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://example.com/");
req.Method = "HEAD";
long len;
using(HttpWebResponse resp = (HttpWebResponse)(req.GetResponse()))
{
    len = resp.ContentLength;
}

لاحظ خاصية طول المحتوى على HttpWebResponse الكائن – لا حاجة لتحليل Content-Length رأس يدويا.

WebClient webClient = new WebClient();
webClient.OpenRead("http://stackoverflow.com/robots.txt");
long totalSizeBytes= Convert.ToInt64(webClient.ResponseHeaders["Content-Length"]);
Console.WriteLine((totalSizeBytes));

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

المعيار System.Net.Http.HttpClient يمكن استخدامها لتحقيق ذلك.يتم طلب المحتوى الجزئي عن طريق تعيين نطاق بايت على رأس رسالة الطلب على النحو التالي:

    request.Headers.Range = new RangeHeaderValue(startByte, endByte)

يستجيب الخادم برسالة تحتوي على النطاق المطلوب بالإضافة إلى حجم الملف بالكامل.يتم إرجاع هذه المعلومات في رأس محتوى الاستجابة (response.Content.Header) باستخدام مفتاح "نطاق المحتوى".

فيما يلي مثال على نطاق المحتوى في رأس محتوى رسالة الرد:

    {
       "Key": "Content-Range",
       "Value": [
         "bytes 0-15/2328372"
       ]
    }

في هذا المثال، تشير قيمة الرأس إلى أن الاستجابة تحتوي على بايتات من 0 إلى 15 (أي إجمالي 16 بايت) وأن الملف يبلغ 2,328,372 بايت بالكامل.

فيما يلي نموذج لتنفيذ هذه الطريقة:

public static class HttpClientExtensions
{
    public static async Task<long> GetContentSizeAsync(this System.Net.Http.HttpClient client, string url)
    {
        using (var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url))
        {
            // In order to keep the response as small as possible, set the requested byte range to [0,0] (i.e., only the first byte)
            request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(from: 0, to: 0);

            using (var response = await client.SendAsync(request))
            {
                response.EnsureSuccessStatusCode();

                if (response.StatusCode != System.Net.HttpStatusCode.PartialContent) 
                    throw new System.Net.WebException($"expected partial content response ({System.Net.HttpStatusCode.PartialContent}), instead received: {response.StatusCode}");

                var contentRange = response.Content.Headers.GetValues(@"Content-Range").Single();
                var lengthString = System.Text.RegularExpressions.Regex.Match(contentRange, @"(?<=^bytes\s[0-9]+\-[0-9]+/)[0-9]+$").Value;
                return long.Parse(lengthString);
            }
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top