2009-06-20 16 views
6

Necesitaré un cliente (usuario final) a través del navegador para cargar archivos grandes (por ejemplo, similar al escenario de Youtube que carga archivos de video grandes), el tamaño del archivo no debe ser mayor a 500M bytes.problema de carga de archivo

Estoy utilizando ASP.Net + C# + VSTS + IIS 7.0 como mi plataforma de desarrollo. ¿Alguna idea o buenas prácticas sobre cómo manejar un problema de carga de archivos grandes? Se aprecia cualquier muestra de referencia o documentos.

Respuesta

2

Las respuestas a this related question recomiendan SWFUpload o NeatUpload para cargar archivos de gran tamaño a través del navegador. NeatUpload es un componente ASP.NET que bien podría adaptarse a su entorno.

También hay JUpload.

+0

Gracias Colin, una pregunta más, ¿por qué es preferible utilizar la solución basada en RIA, ya que es mejor el rendimiento de carga o algo más? – George2

+1

El soporte del navegador para HTTP estándar no permite cosas como especificar qué tipos de archivos están permitidos, también cosas como barras de progreso son mejor compatibles con flash/java –

+0

1. ¿Usando el control FileUpload no se puede especificar el tipo de archivo? Estoy confundido. 2. Creo que el uso de una solución no basada en RIA también podría implementar una barra de progreso, como la forma en que cargamos los archivos adjuntos es Gmail. Por lo tanto, no significa que usar Http simple no puede implementar barra de progreso. ¿Algún comentario? – George2

2

Es necesario configurar maxRequestLength para manejar apropiadamente archivo grande y también establecer executionTimeout para que IIS no abandona la solicitud, en el archivo web.config

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

Detailes mucho más están en here Jon El artículo de Gallowy sobre cargar archivos grandes.

Aquí es artículo sobre MSDN sobre la carga de archivos en asp.net 2.0

+0

Gracias TheVillageIdiot, una pregunta más, ¿por qué es preferible usar una solución basada en RIA, ya que se mejora el rendimiento de carga o algo más? – George2

+1

Creo que con RIA puede dar mejores comentarios para la operación de larga ejecución para el usuario. – TheVillageIdiot

+0

Gracias, 1. ¿así que solo se beneficia la experiencia del usuario? Sin carga de rendimiento u otros beneficios considerables? 2. ¿Por qué usar una solución no basada en RIA no podría tener una buena experiencia de usuario, podría darme un ejemplo, por favor? – George2

1

Casi todos los sitios que manejar grandes cargas, lo hacen de forma predeterminada utilizando Adobe Flash. Por lo general, recurren a una simple carga del navegador, pero administrar las cosas es mucho más fácil hacer el progreso de la carga actual en flash.

+0

Estoy confundido, ¿sugieres que usemos flash o no? – George2

+2

Creo que la recomendación es usar flash (o java), pero permitir la carga HTTP estándar si el usuario no tiene flash/java disponible –

+0

¿por qué es preferible usar una solución flash (o java), porque mejor rendimiento de carga o algo más? – George2

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

¡Esto no funcionará en IIS7! httpRuntime es para IIS6 y más abajo. La forma correcta para permitir la carga de archivos grandes en IIS7 es:

1) Añadir las siguientes líneas al archivo web.config:

[Web.config] maxAllowedContentLength atributo para IIS7

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

2) A continuación, abra el archivo C: \ Windows \ System32 \ inetsrv \ config \ applicationHost.config y encontrar la línea:

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

overrideModeDefault debe Permitir.

+0

Una pregunta sobre el significado del parámetro "executionTimeout" en IIS 6. ¿Significa el tiempo máximo de todo el proceso de carga? O significa tiempo máximo de inactividad (inactivo quiero decir que no se transfiere ningún fragmento de archivo del navegador al servidor, por lo que si continúas transfiriendo fragmentos de archivos, incluso si es lento, no habrá tiempo de espera)? – George2

+0

Otra pregunta es, ¿hay un parámetro para especificar el tiempo de espera en IIS 7? – George2

+0

Estoy casi seguro de que exectutionTimeout también se aplica a IIS7. Preocupado por su primera pregunta: el tiempo de espera especifica la cantidad máxima de segundos que se permite ejecutar una solicitud antes de que ASP.NET la cierre automáticamente. es decir, si su carga no se completa en 110 segundos (de manera predeterminada) ASP cerrará el proceso. –

0

Tuve este problema y encontré la solución basada en Jonathan's code here. Hay algún problema con su código, pero esta es mi solución. Si desea cargar un archivo grande, algo así como un archivo de 1 Gb, debe tirar el archivo y enviarlo a través de varias solicitudes (una solicitud da tiempo de espera). primero establece el límite máximo para el lado del cliente y del servidor.

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

y

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

continuación trozo del archivo, y enviar cada tirada, esperar la respuesta y enviar el siguiente fragmento. aquí está el javascript y el código del controlador.

<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> 

código Javascript a Chuck, controlador de llamada y actualización 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); 
     }); 

y aquí está el controlador de carga para almacenar el chucnk en ("App_Data/Videos/Temp") y luego fusionarlos y almacenar en ("App_Data/Vídeos"):

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

Sin embargo, si dos usuarios en el mismo tiempo subir archivos con el mismo nombre, habrá algún problema, y ​​hay que tratar esta cuestión. Al leer responseText, puede detectar algunos errores y excepciones y recortarlo.

Cuestiones relacionadas