怎样恢复能在asp.net中使用c#下载文件 – >最好的方法(对于大文件也是如此)

看下面的处理程序:

using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace FileExplorer { ///  /// Summary description for HandlerForMyFE ///  public class HandlerForMyFE : IHttpHandler, System.Web.SessionState.IRequiresSessionState { private HttpContext _context; private HttpContext Context { get { return _context; } set { _context = value; } } public void ProcessRequest(HttpContext context) { Context = context; string filePath = context.Request.QueryString["Downloadpath"]; filePath = context.Server.MapPath(filePath); if (filePath == null) { return; } System.IO.StreamReader streamReader = new System.IO.StreamReader(filePath); System.IO.BinaryReader br = new System.IO.BinaryReader(streamReader.BaseStream); byte[] bytes = new byte[streamReader.BaseStream.Length]; br.Read(bytes, 0, (int)streamReader.BaseStream.Length); if (bytes == null) { return; } streamReader.Close(); br.Close(); string fileName = System.IO.Path.GetFileName(filePath); string MimeType = GetMimeType(fileName); string extension = System.IO.Path.GetExtension(filePath); char[] extension_ar = extension.ToCharArray(); string extension_Without_dot = string.Empty; for (int i = 1; i < extension_ar.Length; i++) { extension_Without_dot += extension_ar[i]; } //if (extension == ".jpg") //{ // Handle *.jpg and // WriteFile(bytes, fileName, "image/jpeg jpeg jpg jpe", context.Response); //} //else if (extension == ".gif") //{// Handle *.gif // WriteFile(bytes, fileName, "image/gif gif", context.Response); //} if (HttpContext.Current.Session["User_ID"] != null) { WriteFile(bytes, fileName, MimeType + " " + extension_Without_dot, context.Response); } } private void WriteFile(byte[] content, string fileName, string contentType, HttpResponse response) { response.Buffer = true; response.Clear(); response.ContentType = contentType; response.AddHeader("content-disposition", "attachment; filename=" + fileName); response.BinaryWrite(content); response.Flush(); response.End(); } private string GetMimeType(string fileName) { string mimeType = "application/unknown"; string ext = System.IO.Path.GetExtension(fileName).ToLower(); Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext); if (regKey != null && regKey.GetValue("Content Type") != null) mimeType = regKey.GetValue("Content Type").ToString(); return mimeType; } public bool IsReusable { get { return false; } } } } 

我使用这个处理程序下载我的文件而不直接在浏览器中打开它们 – >(使用查询字符串路径)

如何让我的文件恢复?

我在互联网下载管理器中没有这个选项!

根据要求,这是答案的“清理”版本:

 public static bool DownloadFileMethod(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(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; } 

这是答案!

 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; namespace NiceFileExplorer.Classes { public class DownloadFile { public static bool DownloadFileMethod(HttpContext httpContext, string filePath, long speed) { bool ret = true; try { switch (httpContext.Request.HttpMethod.ToUpper()) { //support Get and head method case "GET": case "HEAD": break; default: httpContext.Response.StatusCode = 501; return false; } if (!File.Exists(filePath)) { httpContext.Response.StatusCode = 404; return false; } //#endregion var fileInfo = new FileInfo(filePath); long startBytes = 0; int packSize = 1024 * 10; //read in block,every 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);//the number of millisecond string lastUpdateTiemStr = File.GetLastWriteTimeUtc(filePath).ToString("r"); string eTag = HttpUtility.UrlEncode(fileName, Encoding.UTF8) + lastUpdateTiemStr; //validate whether the file is too large if (myFile.Length > Int32.MaxValue) { httpContext.Response.StatusCode = 413; return false; } if (httpContext.Request.Headers["If-Range"] != null) { if (httpContext.Request.Headers["If-Range"].Replace("\"", "") != eTag) { httpContext.Response.StatusCode = 412; return false; } } //#endregion try { httpContext.Response.Clear(); httpContext.Response.Buffer = false; httpContext.Response.AddHeader("Content-MD5", GetMD5Hash(fileInfo)); httpContext.Response.AddHeader("Accept-Ranges", "bytes"); httpContext.Response.AppendHeader("ETag", "\"" + eTag + "\""); httpContext.Response.AppendHeader("Last-Modified", lastUpdateTiemStr); httpContext.Response.ContentType = "application/octet-stream"; 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) { httpContext.Response.StatusCode = 206; string[] range = httpContext.Request.Headers["Range"].Split(new char[] { '=', '-' }); startBytes = Convert.ToInt64(range[1]); if (startBytes < 0 || startBytes >= fileLength) { return false; } } if (startBytes > 0) { httpContext.Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength - 1, fileLength)); } //#endregion //send data br.BaseStream.Seek(startBytes, SeekOrigin.Begin); int maxCount = (int)Math.Ceiling((fileLength - startBytes + 0.0) / packSize);//download in block for (int i = 0; i < maxCount && httpContext.Response.IsClientConnected; i++) { 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; } private static string GetMD5Hash(FileInfo file) { var stream = file.OpenRead(); MD5 md5 = new MD5CryptoServiceProvider(); byte[] retVal = md5.ComputeHash(stream); stream.Close(); var sb = new StringBuilder(); for (int i = 0; i < retVal.Length; i++) { sb.Append(retVal[i].ToString("x2")); } return sb.ToString(); } } } 

这是MSDN提供的官方实现:

http://code.msdn.microsoft.com/Implement-resume-in-aspnet-c1bbde36/view/SourceCode

Downloader.cs

 using System; using System.IO; using System.Text; using System.Web; namespace CSASPNETResumeDownload { public class Downloader { public static void DownloadFile(HttpContext httpContext, string filePath) { if (!IsFileExists(filePath)) { httpContext.Response.StatusCode = 404; return; } FileInfo fileInfo = new FileInfo(filePath); if (fileInfo.Length > Int32.MaxValue) { httpContext.Response.StatusCode = 413; return; } // Get the response header information by the http request. HttpResponseHeader responseHeader = GetResponseHeader(httpContext.Request, fileInfo); if (responseHeader == null) { return; } FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); try { SendDownloadFile(httpContext.Response, responseHeader, fileStream); } catch (HttpException ex) { httpContext.Response.StatusCode = ex.GetHttpCode(); } finally { fileStream.Close(); } } ///  /// Check whether the file exists. ///  ///  ///  private static bool IsFileExists(string filePath) { bool fileExists = false; if (!string.IsNullOrEmpty(filePath)) { if (File.Exists(filePath)) { fileExists = true; } } return fileExists; } ///  /// Get the response header by the http request. ///  ///  ///  ///  private static HttpResponseHeader GetResponseHeader(HttpRequest httpRequest, FileInfo fileInfo) { if (httpRequest == null) { return null; } if (fileInfo == null) { return null; } long startPosition = 0; string contentRange = ""; string fileName = fileInfo.Name; long fileLength = fileInfo.Length; string lastUpdateTimeStr = fileInfo.LastWriteTimeUtc.ToString(); string eTag = HttpUtility.UrlEncode(fileName, Encoding.UTF8) + " " + lastUpdateTimeStr; string contentDisposition = "attachment;filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8).Replace("+", "%20"); if (httpRequest.Headers["Range"] != null) { string[] range = httpRequest.Headers["Range"].Split(new char[] { '=', '-' }); startPosition = Convert.ToInt64(range[1]); if (startPosition < 0 || startPosition >= fileLength) { return null; } } if (httpRequest.Headers["If-Range"] != null) { if (httpRequest.Headers["If-Range"].Replace("\"", "") != eTag) { startPosition = 0; } } string contentLength = (fileLength - startPosition).ToString(); if (startPosition > 0) { contentRange = string.Format(" bytes {0}-{1}/{2}", startPosition, fileLength - 1, fileLength); } HttpResponseHeader responseHeader = new HttpResponseHeader(); responseHeader.AcceptRanges = "bytes"; responseHeader.Connection = "Keep-Alive"; responseHeader.ContentDisposition = contentDisposition; responseHeader.ContentEncoding = Encoding.UTF8; responseHeader.ContentLength = contentLength; responseHeader.ContentRange = contentRange; responseHeader.ContentType = "application/octet-stream"; responseHeader.Etag = eTag; responseHeader.LastModified = lastUpdateTimeStr; return responseHeader; } ///  /// Send the download file to the client. ///  ///  ///  ///  private static void SendDownloadFile(HttpResponse httpResponse, HttpResponseHeader responseHeader, Stream fileStream) { if (httpResponse == null || responseHeader == null) { return; } if (!string.IsNullOrEmpty(responseHeader.ContentRange)) { httpResponse.StatusCode = 206; // Set the start position of the reading files. string[] range = responseHeader.ContentRange.Split(new char[] { ' ','=', '-' }); fileStream.Position = Convert.ToInt64(range[2]); } httpResponse.Clear(); httpResponse.Buffer = false; httpResponse.AppendHeader("Accept-Ranges", responseHeader.AcceptRanges); httpResponse.AppendHeader("Connection", responseHeader.Connection); httpResponse.AppendHeader("Content-Disposition", responseHeader.ContentDisposition); httpResponse.ContentEncoding = responseHeader.ContentEncoding; httpResponse.AppendHeader("Content-Length", responseHeader.ContentLength); if (!string.IsNullOrEmpty(responseHeader.ContentRange)) { httpResponse.AppendHeader("Content-Range", responseHeader.ContentRange); } httpResponse.ContentType = responseHeader.ContentType; httpResponse.AppendHeader("Etag", "\"" + responseHeader.Etag + "\""); httpResponse.AppendHeader("Last-Modified", responseHeader.LastModified); Byte[] buffer = new Byte[10240]; long fileLength = Convert.ToInt64(responseHeader.ContentLength); // Send file to client. while (fileLength > 0) { if (httpResponse.IsClientConnected) { int length = fileStream.Read(buffer, 0, 10240); httpResponse.OutputStream.Write(buffer, 0, length); httpResponse.Flush(); fileLength = fileLength - length; } else { fileLength = -1; } } } } ///  /// Respresent the HttpResponse header information. ///  class HttpResponseHeader { public string AcceptRanges { get; set;} public string Connection { get; set; } public string ContentDisposition { get; set; } public Encoding ContentEncoding { get; set; } public string ContentLength { get; set; } public string ContentRange { get; set; } public string ContentType { get; set; } public string Etag { get; set; } public string LastModified { get; set; } } } 

DownloadHttpHandler.ashx.cs

 using System; using System.Configuration; using System.Web; namespace CSASPNETResumeDownload { public class DownloadHttpHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { string filePath = ConfigurationManager.AppSettings["FilePath"]; Downloader.DownloadFile(context, filePath); } public bool IsReusable { get { return false; } } } } 

如果您可以考虑使用ASP.NET Web API,请查看我的postASP.NET Web API文件下载服务,并提供简历支持

它使用两种不同的方法提供解决方案:FileStream类和内存映射文件(这可能会带来一些性能优势)。