2009-06-20 30 views
6

Tôi sẽ cần khách hàng (người dùng cuối) thông qua trình duyệt tải lên tệp lớn (ví dụ: tương tự như trường hợp của YouTube tải lên tệp video lớn), kích thước tệp không được lớn hơn 500M byte.Vấn đề tải lên tệp

Tôi đang sử dụng ASP.Net + C# + VSTS + IIS 7.0 làm nền tảng phát triển của mình. Bất kỳ ý tưởng hoặc thực hành tốt về cách xử lý vấn đề tải lên tệp lớn? Bất kỳ mẫu hoặc tài liệu tham chiếu nào đều được đánh giá cao.

Trả lời

2

Câu trả lời cho this related question đề xuất SWFUpload hoặc NeatUpload để tải lên tệp lớn thông qua trình duyệt. NeatUpload là một chất kết dính ASP.NET có thể phù hợp với môi trường của bạn.

Ngoài ra còn có JUpload.

+0

Cảm ơn Colin, một câu hỏi nữa, tại sao sử dụng giải pháp dựa trên RIA được ưu tiên hơn, vì hiệu suất tải lên tốt hơn hay một thứ gì đó khác? – George2

+1

Hỗ trợ trình duyệt cho HTTP chuẩn không cho phép những thứ như chỉ định loại tệp nào được cho phép, các công cụ như thanh tiến trình được hỗ trợ tốt hơn bởi flash/java –

+0

1. Sử dụng điều khiển FileUpload không thể chỉ định loại tệp? Tôi bị bối rối. 2. Tôi nghĩ rằng việc sử dụng giải pháp dựa trên không dựa trên RIA cũng có thể triển khai thanh tiến trình, như cách chúng tôi tải lên tệp đính kèm là Gmail. Vì vậy, nó không có nghĩa là sử dụng đồng bằng Http không thể thực hiện thanh tiến trình. Có ý kiến ​​gì không? – George2

2

Bạn cần phải thiết lập maxRequestLength để thích hợp xử lý tập tin lớn và cũng đặt executionTimeout để IIS không từ bỏ yêu cầu, trong file web.config nhiều hơn

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

detailes là here trong Jon Bài viết của Gallowy về việc tải lên các tệp lớn.

Dưới đây là bài viết về MSDN về cách tải lên tập tin trong asp.net 2.0

+0

Cảm ơn TheVillageIdiot, một câu hỏi nữa, tại sao sử dụng giải pháp dựa trên RIA được ưa thích, bởi vì hiệu suất tải lên tốt hơn hoặc một cái gì đó khác? – George2

+1

Tôi nghĩ rằng với RIA bạn có thể đưa ra phản hồi tốt hơn cho hoạt động dài hạn cho người dùng. – TheVillageIdiot

+0

Cảm ơn, 1. vì vậy chỉ có lợi ích kinh nghiệm người dùng? Không có hiệu suất tải lên hoặc lợi ích khác 2. Tại sao sử dụng giải pháp dựa trên RIA không thể có trải nghiệm người dùng tốt, bạn có thể cho tôi một ví dụ không? – George2

1

Gần như tất cả các trang web có thể xử lý cập nhật rất lớn như vậy theo mặc định sử dụng Adobe Flash. Thông thường, họ sẽ quay trở lại tải lên trình duyệt đơn giản, nhưng quản lý mọi thứ tiến trình tải lên hiện tại dễ dàng hơn nhiều trong flash.

+0

Tôi bối rối, bạn đề nghị chúng tôi sử dụng đèn flash hay không? – George2

+2

Tôi cho rằng khuyến nghị sử dụng flash (hoặc java), nhưng cho phép tải lên HTTP chuẩn nếu người dùng không có flash/java có sẵn –

+0

lý do tại sao sử dụng giải pháp dựa trên flash (hoặc java) được ưu tiên, vì hiệu suất tải lên tốt hơn hoặc cái gì khác? – George2

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

Điều này sẽ không hoạt động trong IIS7! httpRuntime là dành cho IIS6 và dưới đây. Các cách chính xác để cho phép tải lên tập tin lớn trong IIS7 là:

1) Thêm các dòng sau vào file web.config:

[Web.config] maxAllowedContentLength thuộc tính cho IIS7

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

2) Sau đó, mở tệp C: \ Windows \ System32 \ inetsrv \ config \ applicationHost.config và tìm dòng:

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

ghi đèModeDefault nên cho phép.

+0

Một câu hỏi về ý nghĩa của tham số "executionTimeout" trong IIS 6. Có nghĩa là thời gian tối đa của toàn bộ quá trình tải lên không? Hoặc nó có nghĩa là tối đa thời gian nhàn rỗi (nhàn rỗi tôi có nghĩa là không có tập tin chunk được chuyển từ trình duyệt đến máy chủ, vì vậy nếu tiếp tục chuyển khối tập tin, ngay cả khi chậm, sẽ không có thời gian ra)? – George2

+0

Một câu hỏi khác là, có một tham số để xác định thời gian chờ trong IIS 7? – George2

+0

Tôi gần như chắc chắn rằng exectutionTimeout cũng áp dụng cho IIS7. Trong mối quan tâm với câu hỏi đầu tiên của bạn: thời gian chờ chỉ định số giây tối đa mà một yêu cầu được phép thực thi trước khi được tự động tắt bởi ASP.NET. tức là nếu quá trình tải lên của bạn chưa hoàn thành trong 110 giây (theo mặc định), ASP sẽ tắt quá trình này. –

0

Tôi gặp sự cố này và tìm thấy giải pháp dựa trên Jonathan's code here. Có một số vấn đề với mã của anh ta, nhưng đây là giải pháp của tôi. Nếu bạn muốn tải lên một tập tin lớn, một cái gì đó giống như 1Gbyte tập tin, bạn phải chuck các tập tin và gửi nó thông qua một số yêu cầu (một yêu cầu cho thời gian ra). đầu tiên bạn đặt giới hạn tối đa cho phía máy khách và máy chủ.

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

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

sau đó đoạn tập tin, và gửi mỗi chuck, chờ phản ứng và gửi đoạn tiếp theo. đây là mã javascript và bộ điều khiển.

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

javascript mã để chuck, điều khiển cuộc gọi và cập nhật 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); 
     }); 

và đây là bộ điều khiển tải lên để lưu trữ các chucnk trong ("App_Data/Video/Temp") và sau đó kết hợp chúng và lưu trữ trong ("App_Data/Videos"):

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

Tuy nhiên, nếu hai người dùng cùng một file upload thời gian với cùng một tên, sẽ có một số vấn đề, và bạn phải xử lý vấn đề này. Bằng cách đọc responseText, bạn có thể bắt được một số lỗi và ngoại lệ và cắt nó.