2012-12-28 46 views
13

我有这样的代码,当只有1下载的同时运行如何在下载文件时限制带宽并允许多次下载?

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+下载?

+0

也许看看做这个['任务'](http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.startnew.aspx)并旋转你需要的。此外,您可以查看[本网站](http://www.codethinked.com/net-40-and-systemthreadingtasks)以获取更多示例。 –

+0

我可能是错的,但我认为你不必为此使用多线程。服务器应该自动处理,即使它是一个巨大的文件。你如何测试它?如果他们从2台不同的机器上进行测试并且仍然存在相同的问题呢? – urlreader

+0

使用任务或线程,它在'Response.AddHeader(“Cache-control”,“private”)失败;' 'ArgumentException,值不在预期范围内。' – BrunoLM

回答

1

Google Chrome似乎是用一个唯一的URL来处理下载,所以当我尝试访问相同的URL时,它甚至不会运行该操作。

通过添加任何东西的网址,例如:

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

Chrome会认为这是一个不同的下载,并得到它。所以,要下载文件,即使每次生成不同的文件,我们都需要更改URL。

至于节流我创建了一个FileThrottleResultFilePathResult继承:

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欺骗浏览器即可。