Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>OK so having tried the first answer it did not work as the call to base.WriteFile(response); works asynchronously.</p> <p>I have since written an extension of the FilePathResult class which works by streaming the response. I have also added simple support for file resuming using the range header instruction.</p> <pre><code>public class LoggedFileDownload : FilePathResult { private readonly IRepository repository; private readonly AssetDownload assetDownload; public LoggedFileDownload(string fileName, string contentType, string downloadName, IRepository repository, AssetDownload assetDownload) : base(fileName, contentType) { FileDownloadName = downloadName; this.repository = repository; this.assetDownload = assetDownload; } protected override void WriteFile(HttpResponseBase response) { long totalSent = 0; long bytesRead = 0; var fileInfo = new FileInfo(FileName); var readStream = fileInfo.OpenRead(); var buffer = new Byte[4096]; long responseLength = readStream.Length; var rangeHeader = HttpContext.Current.Request.Headers["Range"]; if (!rangeHeader.IsNullOrEmpty()) { string[] range = rangeHeader.Substring(rangeHeader.IndexOf("=") + 1).Split('-'); long start = Convert.ToInt64(range[0]); long end = 0; if (range[1].Length &gt; 0) end = int.Parse(range[1]); if (end &lt; 1) end = fileInfo.Length; if (start &gt; 0) { responseLength -= start; readStream.Seek(start, 0); totalSent += start; var rangeStr = string.Format("bytes {0}-{1}/{2}", start, end, fileInfo.Length); response.StatusCode = 206; response.AddHeader("Content-Range",rangeStr); } } response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", FileDownloadName)); response.AddHeader("Content-MD5", GetMD5Hash(fileInfo)); response.AddHeader("Accept-Ranges", "bytes"); response.AddHeader("Content-Length", (responseLength).ToString()); response.AddHeader("Connection", "Keep-Alive"); response.ContentType = FileTypeHelper.GetContentType(fileInfo.Name); response.ContentEncoding = Encoding.UTF8; response.Clear(); while(response.IsClientConnected &amp;&amp; (bytesRead = readStream.Read(buffer, 0, buffer.Length)) != 0 ) { totalSent += bytesRead; response.BinaryWrite(buffer); response.Flush(); } if (totalSent == fileInfo.Length) { // This means the file has completely downloaded so we update the DB with the completed field set to true assetDownload.Completed = true; repository.Save(assetDownload); repository.Flush(); } } 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 &lt; retVal.Length; i++) { sb.Append(retVal[i].ToString("x2")); } return sb.ToString(); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload