2009-06-20 26 views
6

Avrò bisogno del client (utente finale) tramite il browser per caricare file di grandi dimensioni (ad esempio simile allo scenario di Youtube che carica file di grandi dimensioni), la dimensione del file non deve essere maggiore di 500 M byte.problema di caricamento file

Sto usando ASP.Net + C# + VSTS + IIS 7.0 come piattaforma di sviluppo. Qualche idea o buona pratica su come gestire il problema del caricamento di file di grandi dimensioni? Qualsiasi campione o documento di riferimento sono apprezzati.

risposta

2

Le risposte a this related question consigliano SWFUpload o NeatUpload per il caricamento di file di grandi dimensioni tramite il browser. NeatUpload è un componente di ASP.NET che potrebbe adattarsi al tuo ambiente.

C'è anche JUpload.

+0

Grazie a Colin, un'altra domanda, perché utilizzare la soluzione basata su RIA è preferibile, perché le migliori prestazioni di caricamento o qualcos'altro? – George2

+1

Il supporto browser per HTTP standard non consente di specificare quali tipi di file sono consentiti, anche le barre di avanzamento sono meglio supportate da flash/java –

+0

1. L'uso del controllo FileUpload non può specificare il tipo di file? Sono confuso. 2. Penso che l'uso di una soluzione non basata su RIA potrebbe anche implementare la barra di avanzamento, come il modo in cui carichiamo l'allegato è Gmail. Quindi, ciò non significa che l'uso di Http non possa implementare la barra di avanzamento. Qualche commento? – George2

2

è necessario impostare maxRequestLength per gestire in modo appropriato file di grandi dimensioni e anche impostare executionTimeout in modo che IIS non abbandona la richiesta, nel file web.config

<system.web> 
    <httpRuntime executionTimeout="300" maxRequestLength="512000" /> 
</system.web> 

Molto più detailes sono here a Jon L'articolo di Gallowy sul caricamento di file di grandi dimensioni.

Ecco articolo su MSDN sul caricamento dei file in asp.net 2.0

+0

Grazie a TheVillageIdiot, un'altra domanda, perché utilizzare la soluzione basata su RIA è preferibile, perché le migliori prestazioni di caricamento o qualcos'altro? – George2

+1

Penso che con RIA si possa fornire un feedback migliore per l'operazione di lunga durata all'utente. – TheVillageIdiot

+0

Grazie, 1. quindi, solo i vantaggi dell'esperienza utente? Nessuna prestazione di upload o altri vantaggi? 2. Perché l'utilizzo di una soluzione non basata su RIA potrebbe non avere una buona esperienza utente, potresti darmi un esempio, per favore? – George2

1

Quasi tutti i siti che gestiscono grandi arrivi lo fanno di default utilizzando Adobe Flash. Di solito ricadono in un semplice caricamento del browser, ma gestendo le cose il progresso del caricamento corrente è molto più facile da fare in flash.

+0

Sono confuso, suggerisci di usare il flash o no? – George2

+2

Penso che la raccomandazione sia utilizzare flash (o java), ma consentire il caricamento HTTP standard se l'utente non ha flash/java disponibile –

+0

perché è preferibile utilizzare la soluzione flash (o java), perché migliori prestazioni di caricamento o qualcos'altro? – George2

6
<system.web> 
     <httpRuntime executionTimeout="300" maxRequestLength="512000" /> 
    </system.web> 

Questo non funzionerà in IIS7! httpRuntime è per IIS6 e qui sotto. Il modo corretto per consentire il caricamento di file di grandi dimensioni in IIS7 è:

1) Aggiungere le seguenti righe al file web.config:

[web.config] maxAllowedContentLength attributo per IIS7

<system.webServer> 
    <security > 
     <requestFiltering> 
      <requestLimits maxAllowedContentLength="1024000000" /> 
     </requestFiltering> 
    </security> 
</system.webServer> 

2) Quindi aprire il file C: \ Windows \ System32 \ inetsrv \ config \ applicationHost.config e trovare la linea:

<section name="requestFiltering" overrideModeDefault="Allow" /> 

overrideModeDefault dovrebbe essere Consenti.

+0

Una domanda sul significato del parametro "executionTimeout" in IIS 6. Significa tempo massimo dell'intero processo di caricamento? O significa tempo di inattività massimo (inattivo significa che nessun blocco di file viene trasferito dal browser al server, quindi se continui a trasferire blocchi di file, anche se lenti, non ci sarà tempo)? – George2

+0

Un'altra domanda è, c'è un parametro per specificare il timeout in IIS 7? – George2

+0

Sono quasi sicuro che exectutionTimeout si applica anche a IIS7. Preoccupato per la tua prima domanda: il timeout specifica il numero massimo di secondi che una richiesta può eseguire prima di essere spenta automaticamente da ASP.NET. Ad esempio, se il caricamento non è completato in 110 secondi (per impostazione predefinita) ASP interromperà il processo. –

0

Ho avuto questo problema e ho trovato la soluzione basata su Jonathan's code here. Ci sono alcuni problemi con il suo codice, ma ecco la mia soluzione. Se vuoi caricare un file di grandi dimensioni, qualcosa come il file 1Gbyte, devi chuck il file e inviarlo attraverso diverse richieste (una richiesta dà timeout). per prima cosa si imposta il limite massimo per lato client e server.

<system.webServer> 
<security> 
    <requestFiltering> 
    <requestLimits maxAllowedContentLength="2147483647" /> 
    </requestFiltering> 
</security> 
<system.webServer> 

e

<system.web> 
    <httpRuntime targetFramework="4.5" maxRequestLength="2147483647" /> 
</system.web> 

poi pezzo il file e inviare ogni mandrino, attendere la risposta e inviare il prossimo pezzo. ecco il codice javascript e controller.

<div id="VideoDiv"> 
     <label>Filename:</label> 
     <input type="file" id="fileInput" /><br/><br/> 
     <input type="button" id="btnUpload" value="Upload a presentation"/><br/><br/> 
     <div id="progressbar_container" style="width: 100%; height: 30px; position: relative; background-color: grey; display: none"> 
      <div id="progressbar" style="width: 0%; height: 100%; position: absolute; background-color: green"></div> 
      <span id="progressbar_label" style="position: absolute; left: 35%; top: 20%">Uploading...</span> 
     </div> 
    </div> 

codice Javascript al mandrino, controllo delle chiamate e aggiornamento progressbar:

 var progressBarStart = function() { 
      $("#progressbar_container").show(); 
     } 

     var progressBarUpdate = function (percentage) { 
      $('#progressbar_label').html(percentage + "%"); 
      $("#progressbar").width(percentage + "%"); 
     } 

     var progressBarComplete = function() { 
      $("#progressbar_container").fadeOut(500); 
     } 

     var file; 

     $('#fileInput').change(function(e) { 
      file = e.target.files[0]; 
     }); 

     var uploadCompleted = function() { 
      var formData = new FormData(); 
      formData.append('fileName', file.name); 
      formData.append('completed', true); 

      var xhr2 = new XMLHttpRequest(); 
      xhr2.onload = function() { 
       progressBarUpdate(100); 
       progressBarComplete(); 
      } 
      xhr2.open("POST", "/Upload/UploadComplete?fileName=" + file.name + "&complete=" + 1, true); 
      xhr2.send(formData); 
     } 

     var multiUpload = function(count, counter, blob, completed, start, end, bytesPerChunk) { 
      counter = counter + 1; 
      if (counter <= count) { 
       var chunk = blob.slice(start, end); 
       var xhr = new XMLHttpRequest(); 
       xhr.onload = function() { 
        start = end; 
        end = start + bytesPerChunk; 
        if (count == counter) { 
         uploadCompleted(); 
        } else { 
         var percentage = (counter/count) * 100; 
         progressBarUpdate(percentage); 
         multiUpload(count, counter, blob, completed, start, end, bytesPerChunk); 
        } 
       } 
       xhr.open("POST", "/Upload/MultiUpload?id=" + counter.toString() + "&fileName=" + file.name, true); 
       xhr.send(chunk); 
      } 
     } 

     $("#VideoDiv").on("click", "#btnUpload", function() { 
      var blob = file; 
      var bytesPerChunk = 3757000; 
      var size = blob.size; 

      var start = 0; 
      var end = bytesPerChunk; 
      var completed = 0; 
      var count = size % bytesPerChunk == 0 ? size/bytesPerChunk : Math.floor(size/bytesPerChunk) + 1; 
      var counter = 0; 
      progressBarStart(); 
      multiUpload(count, counter, blob, completed, start, end, bytesPerChunk); 
     }); 

e qui è il controller di upload per memorizzare il chucnk in ("App_Data/Video/Temp") e poi unirli e conservare in ("App_Data/Video"):

public class UploadController : Controller 
{ 
    private string videoAddress = "~/App_Data/Videos"; 

    [HttpPost] 
    public string MultiUpload(string id, string fileName) 
    { 
     var chunkNumber = id; 
     var chunks = Request.InputStream; 
     string path = Server.MapPath(videoAddress+"/Temp"); 
     string newpath = Path.Combine(path, fileName+chunkNumber); 
     using (FileStream fs = System.IO.File.Create(newpath)) 
     { 
      byte[] bytes = new byte[3757000]; 
      int bytesRead; 
      while ((bytesRead=Request.InputStream.Read(bytes,0,bytes.Length))>0) 
      { 
       fs.Write(bytes,0,bytesRead); 
      } 
     } 
     return "done"; 
    } 

    [HttpPost] 
    public string UploadComplete(string fileName, string complete) 
    { 
     string tempPath = Server.MapPath(videoAddress + "/Temp"); 
     string videoPath = Server.MapPath(videoAddress); 
     string newPath = Path.Combine(tempPath, fileName); 
     if (complete=="1") 
     { 
      string[] filePaths = Directory.GetFiles(tempPath).Where(p=>p.Contains(fileName)).OrderBy(p => Int32.Parse(p.Replace(fileName, "$").Split('$')[1])).ToArray(); 
      foreach (string filePath in filePaths) 
      { 
       MergeFiles(newPath, filePath); 
      } 
     } 
     System.IO.File.Move(Path.Combine(tempPath, fileName),Path.Combine(videoPath,fileName)); 
     return "success"; 
    } 

    private static void MergeFiles(string file1, string file2) 
    { 
     FileStream fs1 = null; 
     FileStream fs2 = null; 
     try 
     { 
      fs1 = System.IO.File.Open(file1, FileMode.Append); 
      fs2 = System.IO.File.Open(file2, FileMode.Open); 
      byte[] fs2Content = new byte[fs2.Length]; 
      fs2.Read(fs2Content, 0, (int) fs2.Length); 
      fs1.Write(fs2Content, 0, (int) fs2.Length); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message + " : " + ex.StackTrace); 
     } 
     finally 
     { 
      if (fs1 != null) fs1.Close(); 
      if (fs2 != null) fs2.Close(); 
      System.IO.File.Delete(file2); 
     } 
    } 
} 

Tuttavia, se due utenti allo stesso tempo caricare file con lo stesso nome, ci sarà qualche problema, e si deve gestire questo problema. Leggendo responseText, puoi rilevare alcuni errori ed eccezioni e tagliarli.

Problemi correlati