Подтвердить что ты не робот

Как ограничить пропускную способность и разрешить несколько загрузок при загрузке файла?

У меня есть этот код, который работает, когда работает только одна загрузка за один раз

using (System.IO.FileStream fs = System.IO.File.OpenRead(@"C:\HugeFile.GBD"))
{
    using (System.IO.BinaryReader br = new System.IO.BinaryReader(fs))
    {
        Response.AddHeader("Cache-control", "private");
        Response.AddHeader("Content-Type", "application/octet-stream");
        Response.AddHeader("Content-Length", fs.Length.ToString());
        Response.AddHeader("Content-Disposition", "filename=HugeFile.GBD");
        Response.Flush();
        float kbs = 20f;

        while (fs.Position < fs.Length)
        {
            if (!Response.IsClientConnected)
                break;
            byte[] bytes = br.ReadBytes((int)Math.Truncate(1024 * kbs));
            char[] c = UTF8Encoding.Default.GetChars(bytes);

            Response.Write(c, 0, c.Length);


            Response.Flush();
            System.Threading.Thread.Sleep(1000);
        }
        Response.Flush();
    }
}

Но если я делаю два одновременных соединения (начните вторую загрузку в одном браузере), второй не будет выполняться до тех пор, пока не закончится первый.

Использование потока или задачи приводит к ошибке при добавлении заголовков в Response...

Как я могу сделать это, чтобы одновременно выполнять 2+ загрузки в одном браузере?

4b9b3361

Ответ 1

Кажется, Google Chrome обрабатывает загрузку с уникальным URL-адресом, поэтому, когда я пытаюсь получить доступ к одному и тому же URL-адресу, он даже не запускает действие.

Добавив что-либо к URL-адресу, например:

home/download?x=1
home/download?x=2
home/download?x=3

Chrome подумает, что это другая загрузка и получить ее. Таким образом, для скачивания файла, даже если каждый раз созданный файл нужно изменить, нам нужно изменить URL.

И что касается дросселя, я создал a FileThrottleResult, который наследует от FilePathResult:

using System;
using System.IO;
using System.Threading;
using System.Web.Mvc;

namespace Mvc3Test
{
    public class FileThrottleResult : FilePathResult
    {
        float rate = 0;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="contentType"></param>
        /// <param name="rate">Kbps</param>
        public FileThrottleResult(string fileName, string contentType, float rate)
            : base(fileName, contentType)
        {
            if (!File.Exists(fileName))
            {
                throw new ArgumentNullException("fileName");
            }
            this.rate = rate;
        }

        protected override void WriteFile(System.Web.HttpResponseBase response)
        {
            int _bufferSize = (int)Math.Round(1024 * this.rate);
            byte[] buffer = new byte[_bufferSize];

            Stream outputStream = response.OutputStream;

            using (var stream = File.OpenRead(FileName))
            {
                response.AddHeader("Cache-control", "private");
                response.AddHeader("Content-Type", "application/octet-stream");
                response.AddHeader("Content-Length", stream.Length.ToString());
                response.AddHeader("Content-Disposition", String.Format("filename={0}", new FileInfo(FileName).Name));
                response.Flush();

                while (true)
                {
                    if (!response.IsClientConnected)
                        break;

                    int bytesRead = stream.Read(buffer, 0, _bufferSize);
                    if (bytesRead == 0)
                        break;

                    outputStream.Write(buffer, 0, bytesRead);
                    response.Flush();
                    Thread.Sleep(1000);
                }
            }
        }
    }
}

Использование:

public FileThrottleResult Download()
{
    string testFile = @"C:\hugefile.zip";
    return new FileThrottleResult(testFile, "application/octet-stream", 200);
}

Это позволит ограничить пропускную способность и не будет иметь проблем с одновременной загрузкой одного и того же файла, если вы обманете браузер с помощью "другого" URL-адреса.