asp.net file download the implementation code

  • 2020-05-09 18:24:51
  • OfStack


public static bool DownloadFile(HttpContext httpContext, string filePath, long speed) 
{ 
bool ret = true; 
try 
{ 
#region-- Validation: HttpMethod , whether the requested file exists  
switch (httpContext.Request.HttpMethod.ToUpper()) 
{ // Currently only supported GET and HEAD methods  
case "GET": 
case "HEAD": 
break; 
default: 
httpContext.Response.StatusCode = 501; 
return false; 
} 
if (!File.Exists(filePath)) 
{ 
httpContext.Response.StatusCode = 404; 
return false; 
} 
#endregion 
#region  Define local variables  
long startBytes = 0; 
int packSize = 1024 * 10; // Read in blocks, each block 10K bytes 
string fileName = Path.GetFileName(filePath); 
FileStream myFile = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
BinaryReader br = new BinaryReader(myFile); 
long fileLength = myFile.Length; 
int sleep = (int)Math.Ceiling(1000.0 * packSize / speed);// Milliseconds: read down 1 The time interval of the data block  
string lastUpdateTiemStr = File.GetLastWriteTimeUtc(filePath).ToString("r"); 
string eTag = HttpUtility.UrlEncode(fileName, Encoding.UTF8) + lastUpdateTiemStr;// It is easy to extract the request header when restoring the download ; 
#endregion 
#region-- Verify: whether the file is too large, whether it is retransmitted, and whether it has been fixed since the last requested date  
if (myFile.Length > Int32.MaxValue) 
{//------- The file is too big ------- 
httpContext.Response.StatusCode = 413;// The requesting entity is too large  
return false; 
} 

if (httpContext.Request.Headers["If-Range"] != null)// Corresponding response header ETag : the name of the file + File last modified  
{ 
//---------- The last requested date has been modified since -------------- 
if (httpContext.Request.Headers["If-Range"].Replace("\"", "") != eTag) 
{// The file has been modified  
httpContext.Response.StatusCode = 412;// Pretreatment failure  
return false; 
} 
} 
#endregion 
try 
{ 
#region ------- Add important response headers, parse request headers, and related validation ------------------- 
httpContext.Response.Clear(); 
httpContext.Response.Buffer = false; 
httpContext.Response.AddHeader("Content-MD5", GetMD5Hash(myFile));// Used to validate files  
httpContext.Response.AddHeader("Accept-Ranges", "bytes");// Important: must continue  
httpContext.Response.AppendHeader("ETag", "\"" + eTag + "\"");// Important: must continue  
httpContext.Response.AppendHeader("Last-Modified", lastUpdateTiemStr);// Write the last modified date to the response  
httpContext.Response.ContentType = "application/octet-stream";//MIME Type: matches any file type  
httpContext.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8).Replace("+", "%20")); 
httpContext.Response.AddHeader("Content-Length", (fileLength - startBytes).ToString()); 
httpContext.Response.AddHeader("Connection", "Keep-Alive"); 
httpContext.Response.ContentEncoding = Encoding.UTF8; 
if (httpContext.Request.Headers["Range"] != null) 
{//------ If it is a continuation request, it gets the starting position of the continuation, that is, the number of bytes that have been downloaded to the client ------ 
httpContext.Response.StatusCode = 206;// Important: must continue the transmission, represents the local range response. Default at initial download 200 
string[] range = httpContext.Request.Headers["Range"].Split(new char[] { '=', '-' });//"bytes=1474560-" 
startBytes = Convert.ToInt64(range[1]);// The number of bytes that have been downloaded, where the download started  
if (startBytes < 0 || startBytes >= fileLength) 
{// Invalid start position  
return false; 
} 
} 
if (startBytes > 0) 
{//------ If it is a continuation request, tell the client the starting number of bytes and the total length so that the client can append the continuation data to startBytes After the position ---------- 
httpContext.Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength - 1, fileLength)); 
} 
#endregion 
#region ------- Sends a block of data to the client ------------------- 
br.BaseStream.Seek(startBytes, SeekOrigin.Begin); 
int maxCount = (int)Math.Ceiling((fileLength - startBytes + 0.0) / packSize);// The number of blocks that can be divided into the remaining parts  
for (int i = 0; i < maxCount && httpContext.Response.IsClientConnected; i++) 
{// When the client breaks the connection, it is suspended  
httpContext.Response.BinaryWrite(br.ReadBytes(packSize)); 
httpContext.Response.Flush(); 
if (sleep > 1) Thread.Sleep(sleep); 
} 
#endregion 
} 
catch 
{ 
ret = false; 
} 
finally 
{ 
br.Close(); 
myFile.Close(); 
} 
} 
catch 
{ 
ret = false; 
} 
return ret; 
}

Related articles: