2013-04-29 14 views
34

私はそれが働いていた..しかし、私はかつて私は、コントローラが呼び出されないでしょう(4000K前後)より大きな取得アップロードされたファイル.. MVC 4を使用して大きなファイルをアップロードするには?

は、だから私はその問題を固定チャンキングで追加さに気づいた..しかし、今とき、私ファイルをガベージ文字でいっぱいにしてください。

plupload/MVC 4で大きなファイルをアップロードする正しい方法は何ですか?

ここに私の現在のコード

$(document).ready(function() { 

    var uploader = new plupload.Uploader({ 
     runtimes: 'html5', 
     browse_button: 'pickfiles', 
     container: 'container', 
    // max_file_size: '20000mb', 
     url: '@Url.Action("Upload", "Home")', 
     chunk_size: '4mb', 
     //filters: [ 
     // { title: "Excel files", extensions: "xls,xlsx" }, 
     // { title: "Text files", extensions: "txt" } 
     //], 
     multiple_queues: true, 
     multipart: true, 
     multipart_params: { taskId: '' } 
    }); 

、あなたが(すべての周り2GB)これらを必要とするweb.configファイルでコントローラ

[HttpPost] 
    public ActionResult Upload(int? chunk, string name, string taskId) 
    { 
     string filePath = ""; 
     var fileUpload = Request.Files[0]; 
     var uploadPath = Server.MapPath("~/App_Data/Uploads"); 
     chunk = chunk ?? 0; 
     string uploadedFilePath = Path.Combine(uploadPath, name); 
     var fileName = Path.GetFileName(uploadedFilePath); 

try 
     { 
      using (var fs = new FileStream(filePath, chunk == 0 ? FileMode.Create : FileMode.Append)) 
      { 
       var buffer = new byte[fileUpload.InputStream.Length]; 
       fileUpload.InputStream.Read(buffer, 0, buffer.Length); 
       fs.Write(buffer, 0, buffer.Length); 
      } 

      //Log to DB for future processing 
      InstanceExpert.AddProcessStart(filePath, Int32.Parse(taskId)); 
     } 
+1

4MBのファイルは、ASP.NETでチャンクすることなく処理できる必要があります。アップロードファイルの最大サイズを大きくするか、実行時間を長くする必要があるかもしれません。 –

+0

私がアップロードしているこの最大のファイルは7268kです。チャンクが必要ですか?または私は何を変えますか? – punkouter

+0

web.configの 'maxRequestLength'を変更してください。変更する必要がある例については、http://stackoverflow.com/a/288675/254973を参照してください。その後、plUploadがチャンクアップロードを送信しないように、javunkから 'chunk_size'オプションを削除してください。 –

答えて

55

です:

<system.web> 
    <compilation debug="true" targetFramework="4.5" /> 
    <httpRuntime targetFramework="4.5" maxRequestLength="2147483647" executionTimeout="1600" requestLengthDiskThreshold="2147483647" /> 
    <security> 
     <requestFiltering> 
     <requestLimits maxAllowedContentLength="2147483647" /> 
     </requestFiltering> 
    </security> 
    ... 
</system.web> 
+0

ありがとうシェーン!これは私の "イントラネット"アプリケーションのために働いていましたが、私は targetFramework = "4.0" を使っていますので、私にはセクションがありません。私は300MBと700MBの間の制限を持って終わった。私は正確な限界を見つけるために完全にテストしていません。 – Colin

+4

あなたはではないと思います。たぶん異なるバージョンでは違うかもしれません。 – jwize

+0

ウェブサイトの場合system.web – ShaneKm

11

現在のバージョンは、

この回答を書いた時点で使用していたIIS 8.0の詳細なエラーの説明によれば、ApplicationHost.configまたはWeb.configファイルのconfiguration/system.webServer/security/requestFiltering/requestLimits @maxAllowedContentLength設定を確認する必要があります。つまり、次の情報を含める必要があります。

<requestLimits maxAllowedContentLength="20971520000"></requestLimits> 

inside configuration/system.webServer/security/requestFilteringタグツリー。ちょうどあなたがそれがどこに行くか視覚化するための想像力に欠けている場合には、完全なコードブロックは次のようになります:

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

のVisual Studio 2010/.NET Frameworkの4と

前にそれは可能性もありますVS2008/10および/または.Net Framework 3.5/4で作成された従来のWebアプリケーションは、configuration/system.web/httpRuntime @ maxRequestLength経由でこの設定を探している可能性がありますが、リンクされたページからもわかるように、利用できません。HttpRuntime Classこのシナリオに適用され、.Net Framework 1.1以降はまだ存在します。この場合、次の情報を含める必要があります。

<httpRuntime maxRequestLength="20971520000" /> 

inside configuration/system.web/httpRuntimeタグツリー。 - ない

<configuration> 
    <system.web> 
     <httpRuntime maxRequestLength="20971520000" /> 
    </system.web> 
</configuration> 

ファイルサイズの数だけで任意の番号(2万メガバイトです:もう一度、あなたはそれが挿入されます場所を把握するわかりやすさが不足しているだけの場合には、完全なコードブロックは次のようになります20 GB、これはむしろ21,474,836,480になります)をデモとして表示します。大規模なファイルをアップロードする必要がある緊密なセキュリティグループのWebサイトをコーディングしている場合を除き、Webサーバーにアップロードされるファイルサイズを大きくしないでください。

4

私はこの問題を抱え、Jonathan's code hereに基づいて解決策を見つけました。彼のコードにはいくつかの問題がありますが、ここに私の解決策があります。 1Gバイトのファイルのような大きなファイルをアップロードする場合は、ファイルをチャックしていくつかの要求(1つの要求がタイムアウトになる)で送信する必要があります。前に説明したように、クライアント側とサーバー側の最大限度を設定します。その後、

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

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

チャンクファイルを、応答を待ち、次のチャンクを送信する、各チャックを送ります。ここにはJavaScriptとコントローラのコードがあります。

<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コードは、チャックのコントローラを呼び出し、プログレスバーを更新する:

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

、ここでは、(「App_Dataに/ビデオ/温度」)にchucnkを格納するためのアップロードコントローラで、後でそれらをマージし、 (「App_Dataに/ビデオ」)で保存:

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

しかし、同じ名前で同じ時間アップロードファイルに2人のユーザーは、いくつかの問題があるでしょう、そしてあなたは、この問題に対処する必要がある場合。 responseTextを読むことで、何らかのエラーと例外を捕まえてトリムすることができます。

関連する問題