断点下载帮助方法

发布时间 2023-10-19 14:18:26作者: 码农阿亮

核心代码

 public static class DownloadHelper
 {
     /// <summary>
     /// 断点下载
     /// </summary>
     /// <param name="controller"></param>
     /// <param name="fullpath"></param>
     /// <returns></returns>
     public static async Task<long> RangeDownload(this Controller controller, string fullpath,string filename)
     {
         long size, start, end, length, fp = 0;
         using (StreamReader reader = new StreamReader(File.OpenRead(fullpath)))
         {

             size = reader.BaseStream.Length;
             start = 0;
             end = size - 1;
             length = size;
          
             controller.Response.Headers.Add("Accept-Ranges", "0-" + size);

             if (!String.IsNullOrEmpty(controller.Request.Headers["Range"]))
             {
                 long anotherStart = start;
                 long anotherEnd = end;
                 string[] arr_split = controller.Request.Headers["Range"].FirstOrDefault().Split(new char[] { Convert.ToChar("=") });
                 string range = arr_split[1];

                 if (range.IndexOf(",") > -1)
                 {
                     controller.Response.Headers.Add("Content-Range", "bytes " + start + "-" + end + "/" + size);
                     controller.Response.StatusCode = 416;
                 }

                 if (range.StartsWith("-"))
                 {
                     anotherStart = size - Convert.ToInt64(range.Substring(1));
                 }
                 else
                 {
                     arr_split = range.Split(new char[] { Convert.ToChar("-") });
                     anotherStart = Convert.ToInt64(arr_split[0]);
                     long temp = 0;
                     anotherEnd = (arr_split.Length > 1 && Int64.TryParse(arr_split[1].ToString(), out temp)) ? Convert.ToInt64(arr_split[1]) : size;
                 }

                 anotherEnd = (anotherEnd > end) ? end : anotherEnd;
                 if (anotherStart > anotherEnd || anotherStart > size - 1 || anotherEnd >= size)
                 {

                     controller.Response.Headers.Add("Content-Range", "bytes " + start + "-" + end + "/" + size);
                     controller.Response.StatusCode = 416;
                     await controller.Response.WriteAsync("Requested Range Not Satisfiable");
                 }
                 start = anotherStart;
                 end = anotherEnd;

                 length = end - start + 1;
                 fp = reader.BaseStream.Seek(start, SeekOrigin.Begin);
                 controller.Response.StatusCode = 206;
             }
         }
         // Notify the client the byte range we‘ll be outputting
         controller.Response.Headers.Add("Content-Range", "bytes " + start + "-" + end + "/" + size);
         controller.Response.Headers.Add("Content-Length", length.ToString());
         controller.Response.Headers.Add("Content-Disposition", $"attachment; filename={filename}") ;
         // Start buffered download
         await controller.Response.SendFileAsync(fullpath, fp, length);
         return fp;
     }
 }