2012-12-28 78 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欺騙瀏覽器即可。