2011-11-09 8 views
1

iはresumeableファイルのダウンロードのためのstackoverflowで以下のコードを見つけました:resumeableファイルのダウンロードの問題 - >にファイルサイズがInt32.MaxValueを(2GB)を超えている(大きなファイル)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Text; 
using System.IO; 
using System.Threading; 
using System.Security.Cryptography; 
using System.Net; 

namespace WindowsServer.Classes 
{ 
    public class DownloadFile 
    { 

     public static bool DownloadFileMethod_2(HttpContext httpContext, string filePath, long speed) 
     { 
      // Many changes: mostly declare variables near use 
      // Extracted duplicate references to HttpContext.Response and .Request 
      // also duplicate reference to .HttpMethod 

      // Removed try/catch blocks which hid any problems 
      var response = httpContext.Response; 
      var request = httpContext.Request; 
      var method = request.HttpMethod.ToUpper(); 
      if (method != "GET" && 
       method != "HEAD") 
      { 
       response.StatusCode = 501; 
       return false; 
      } 

      if (!File.Exists(filePath)) 
      { 
       response.StatusCode = 404; 
       return false; 
      } 

      // Stream implements IDisposable so should be in a using block 
      using (var myFile = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
      { 
       var fileLength = myFile.Length; 
       if (fileLength > Int32.MaxValue) 
       { 
        response.StatusCode = 413; 
        return false; 
       } 

       var lastUpdateTiemStr = File.GetLastWriteTimeUtc(filePath).ToString("r"); 
       var fileName = Path.GetFileName(filePath); 
       var fileNameUrlEncoded = HttpUtility.UrlEncode(fileName, Encoding.UTF8); 
       var eTag = fileNameUrlEncoded + lastUpdateTiemStr; 

       var ifRange = request.Headers["If-Range"]; 
       if (ifRange != null && ifRange.Replace("\"", "") != eTag) 
       { 
        response.StatusCode = 412; 
        return false; 
       } 

       long startBytes = 0; 

       // Just guessing, but I bet you want startBytes calculated before 
       // using to calculate content-length 
       var rangeHeader = request.Headers["Range"]; 
       if (rangeHeader != null) 
       { 
        response.StatusCode = 206; 
        var range = rangeHeader.Split(new[] { '=', '-' }); 
        startBytes = Convert.ToInt64(range[1]); 
        if (startBytes < 0 || startBytes >= fileLength) 
        { 
         // TODO: Find correct status code 
         response.StatusCode = (int)HttpStatusCode.BadRequest; 
         response.StatusDescription = 
          string.Format("Invalid start of range: {0}", startBytes); 
         return false; 
        } 
       } 

       response.Clear(); 
       response.Buffer = false; 
       response.AddHeader("Content-MD5", GetMD5Hash_2(filePath)); 
       response.AddHeader("Accept-Ranges", "bytes"); 
       response.AppendHeader("ETag", string.Format("\"{0}\"", eTag)); 
       response.AppendHeader("Last-Modified", lastUpdateTiemStr); 
       response.ContentType = "application/octet-stream"; 
       response.AddHeader("Content-Disposition", "attachment;filename=" + 
                  fileNameUrlEncoded.Replace("+", "%20")); 
       var remaining = fileLength - startBytes; 
       response.AddHeader("Content-Length", remaining.ToString()); 
       response.AddHeader("Connection", "Keep-Alive"); 
       response.ContentEncoding = Encoding.UTF8; 

       if (startBytes > 0) 
       { 
        response.AddHeader("Content-Range", 
             string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength - 1, fileLength)); 
       } 

       // BinaryReader implements IDisposable so should be in a using block 
       using (var br = new BinaryReader(myFile)) 
       { 
        br.BaseStream.Seek(startBytes, SeekOrigin.Begin); 

        const int packSize = 1024 * 10; //read in block,every block 10K bytes 
        var maxCount = (int)Math.Ceiling((remaining + 0.0)/packSize); //download in block 
        for (var i = 0; i < maxCount && response.IsClientConnected; i++) 
        { 
         response.BinaryWrite(br.ReadBytes(packSize)); 
         response.Flush(); 

         // HACK: Unexplained sleep 
         var sleep = (int)Math.Ceiling(1000.0 * packSize/speed); //the number of millisecond 
         if (sleep > 1) Thread.Sleep(sleep); 
        } 
       } 
      } 
      return true; 
     } 

     static string GetMD5Hash_2(string input) 
     { 
      // Create a new instance of the MD5CryptoServiceProvider object. 
      MD5 md5Hasher = MD5.Create(); 

      // Convert the input string to a byte array and compute the hash. 
      byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input)); 

      // Create a new Stringbuilder to collect the bytes 
      // and create a string. 
      StringBuilder sBuilder = new StringBuilder(); 

      // Loop through each byte of the hashed data 
      // and format each one as a hexadecimal string. 
      for (int i = 0; i < data.Length; i++) 
      { 
       sBuilder.Append(data[i].ToString("x2")); 
      } 

      // Return the hexadecimal string. 
      return sBuilder.ToString(); 
     } 

    } 
} 

この方法は、時にfalseを返しますファイルサイズがInt32.MaxValueより大きい!
10GB以上の大容量ファイルに対してこの方法を変更するにはどうすればよいですか?

+0

その人はその質問のために破壊されたようだ...(貧しい人)(彼のためにとても悲しい!)/親愛なる友人たちは、私たちはここで勉強しています。 – MoonLight

答えて

5

コードは、ファイルサイズがInt32.MaxValueをより大きい場合はfalseリターン含まれているので、それはfalseを返します。それは、あなたの質問に答えるん

var fileLength = myFile.Length; 
     if (fileLength > Int32.MaxValue) 
     { 
      response.StatusCode = 413; 
      return false; 
     } 

を、またはあなたが知りたい元のコードを追加した理由その句?理由を理解できない場合は、intertubezにあるこのランダムコードを使用してもよろしいですか?

+0

簡単なデバッグでもこの問題が検出されていました。 – McKay

+2

あなたが理解していないコードを使用しない理由の完全な例。 –

+0

こんにちは、お返事ありがとうございます!私はそのコードを理解し、その状態が決して真実ではないことを知っています!しかし、私は2 GBを超えるファイルをダウンロードするための最良の方法を取得するためのプロの人々にその方法を示したい! (平均値編集とカスタマイズ) – MoonLight

1
var fileLength = myFile.Length; 

ここではvarを使用しました。 fileLengthlongで十分です。

if (fileLength > Int32.MaxValue) 
    { 
     response.StatusCode = 413; 
     return false; 
    } 

と思われます。

+0

'var'とは何が関係していますか? – Gabe

+2

@gabe Stream.Lengthは誰もが知っているわけではありません。私はここで 'var'を使用しません。 –

+0

私はそれが 'long'だったのかどうかはわかりませんでしたが、' int'の場合、 'fileLength> Int32.MaxValue'は決して真ではありません。 – Gabe

関連する問題