Resumable file download in MVC Core code example

Example: Resumable file download in MVC Core

using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;

namespace Sample.Controllers
{
	public class HomeController : Controller
	{
		[HttpHead]
		[HttpGet]
		public void Download()
		{
			// File to download
			FileInfo pdf = new FileInfo(@"D:\Edge\bigfile.bin");
			if (Request.Method == "HEAD")
				SetResponseHeaders(pdf);
			else
				DownloadContent(pdf);
		}

		private IActionResult DownloadContent(FileInfo pdf)
		{
			Response.Headers.Add("Accept-Ranges", "bytes");
			Response.Headers.Add("Content-Disposition", $"attachment; filename={pdf.Name}");
			//
			long start = 1, end = pdf.Length, length;
			byte[] buffer;
			if (Request.Headers["Range"].Count > 0 && Request.Headers["Range"][0] != null)
			{
				string[] range = Request.Headers["Range"][0].Split(new[] { '=', '-' });
				if (range.Length > 1) long.TryParse(range[1], out start);
				if (start <= 0 || start > pdf.Length) start = 1;
				if (range.Length > 2) long.TryParse(range[2], out end);
				if (end > pdf.Length || end <= 0) end = pdf.Length;
			}
			else
			{
				// If no Range header found, send the entire file content
				start = 1;
				end = pdf.Length;
			}
			length = end - start + 1;
			buffer = new byte[length];
			Response.ContentLength = length;
			if (Request.Headers["Range"].Count > 0)
			{
				Response.StatusCode = 206;
				Response.Headers.Add("Content-Range", $"bytes {start}-{end}/{pdf.Length}");
			}
			else
			{
				Response.StatusCode = 200;
			}
			FileStream fs = new FileStream(pdf.FullName, FileMode.Open);
			if (fs.CanSeek)
			{
				fs.Seek(start - 1, SeekOrigin.Begin);
				int read = fs.Read(buffer, 0, (int)length);
				fs.Close();
				Response.Body.Write(buffer, 0, buffer.Length);
			}
			else
			{
				//Response.Body.Write($"Can't return content range.");
			}
		}

		private void SetResponseHeaders (FileInfo pdf)
		{
			Response.StatusCode = 200;
			Response.Headers.Add("Accept-Ranges", "bytes");
			Response.ContentType = "application/octet-stream"; // Change MIME based on file type
			Response.Headers.Add("Content-Disposition", $"attachment; filename={pdf.Name}");
			Response.ContentLength = pdf.Length;
		}
	}
}

Tags:

Misc Example