2012-12-28 12 views
13

Ho questo codice, che sta lavorando quando soltanto 1 download è in esecuzione in un momentoCome limitare la larghezza di banda e consentire download multipli durante il download di un file?

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(); 
    } 
} 

Ma se faccio due connessioni simultanee (avviare una seconda scaricare sullo stesso browser) il secondo non esegue fino a quando il primo finisce.

Utilizzando un filo o un compito produce un errore quando si aggiungono le intestazioni al Response ...

Come posso fare in modo che possa eseguire 2+ download sullo stesso browser, allo stesso tempo?

+0

Forse guardate a fare di questo un ['Task'] (http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.startnew.aspx) e girate su quelli che vi servono . Inoltre, puoi dare un'occhiata a [questo sito] (http://www.codethinked.com/net-40-and-systemthreadingtasks) per ulteriori esempi. –

+0

Potrei sbagliarmi, ma penso che non devi usare il multithread per questo. il server dovrebbe gestire automaticamente anche questo è un file enorme. Come lo test? cosa succede se lo provano da 2 macchine diverse e hanno ancora lo stesso problema? – urlreader

+0

Utilizzo di attività o thread, non riesce a 'Response.AddHeader (" Cache-control "," private ");' 'ArgumentException, il valore non rientra nell'intervallo previsto. – BrunoLM

risposta

1

Sembra che Google Chrome gestisca un download con un URL univoco, quindi quando provo ad accedere allo stesso URL non esegue nemmeno l'azione.

Con l'aggiunta di qualsiasi cosa per l'URL, ad esempio:

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

Chrome penseranno che è un download diversa e farlo. Quindi, per scaricare un file, anche se un file generato diverso ogni volta, dobbiamo cambiare l'URL.

E per quanto riguarda il gas ho creato un FileThrottleResult che eredita da 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); 
       } 
      } 
     } 
    } 
} 

Usage:

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

Ciò limiterà con successo la larghezza di banda e non avrà problemi con download simultanei del stesso file, a condizione di ingannare il browser con un URL "diverso".

Problemi correlati