Hỏi cách download chunk/segment sử dụng C# với custom referer header

Discussion in 'Hỏi Đáp Kỹ Thuật' started by dev9x, Feb 12, 2021.

  1. firefox

    firefox Bang Chúng

    không chắc nhưng thử cách này xem. Em đi ngủ đã, bye bác

    Code:
    using System;
    using System.Collections.Generic;
    using System.Collections.Concurrent;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Threading.Tasks;
    using YouTubeRenderTools.YouTubeRenderTools;
    
    
    namespace YouTubeRenderTools
    {
        class Program
        {
            static void Main(string[] args)
            {
                Directory.CreateDirectory("test");
                var downloadResult = Downloader.Download("http://learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4", "test", "test.mp4", totalThreads: 4);
                Console.WriteLine(downloadResult.TimeTaken.TotalMilliseconds.ToString("N0"));
            }
        }
    
    
        namespace YouTubeRenderTools
        {
            public class DownloadResult
            {
                public long Size { get; set; }
                public String FilePath { get; set; }
                public TimeSpan TimeTaken { get; set; }
                public int ParallelDownloads { get; set; }
                public float Progress;
            }
    
            public class DownloadParams
            {
                public int id;
                public string savePath;
                public string fileName;
                public int totalThreads;
                public Action<float> onProgress;
                public Action onFinish;
            }
    
            internal class Range
            {
                public long Start { get; set; }
                public long End { get; set; }
                public int ChunkIndex { get; set; }
            }
    
            public static class Downloader
            {
                static Downloader()
                {
                    ServicePointManager.Expect100Continue = false;
                    ServicePointManager.DefaultConnectionLimit = 100;
                    ServicePointManager.MaxServicePointIdleTime = 1000;
                }
    
                public static DownloadResult Download(string fileUrl, string savePath, string fileName, int totalThreads = 1, bool validateSSL = false)
                {
                    if (!validateSSL)
                    {
                        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                    }
    
                    var uri = new Uri(fileUrl);
    
                    var destinationFilePath = Path.Combine(savePath, fileName);
    
                    var result = new DownloadResult {FilePath = destinationFilePath};
    
                    if (totalThreads <= 0)
                    {
                        totalThreads = Environment.ProcessorCount;
                    }
    
                    #region Get file size
    
                    var webRequest = (HttpWebRequest) WebRequest.Create(fileUrl);
                    //   webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36";
                    //   webRequest.Headers.Add("Origin", "https://ok.ru");
                    webRequest.Method = "HEAD";
                    long responseLength;
                    using (var webResponse = webRequest.GetResponse())
                    {
                        responseLength = long.Parse(webResponse.Headers.Get("Content-Length") ?? "0");
                        result.Size = responseLength;
                    }
    
                    #endregion
    
                    Console.WriteLine("responseLength : " + responseLength);
                    Console.WriteLine("destinationFilePath : " + destinationFilePath);
    
    
                    if (File.Exists(destinationFilePath))
                    {
                        File.Delete(destinationFilePath);
                    }
    
                    using (var destinationStream = new FileStream(destinationFilePath, FileMode.Append))
                    {
                        var tempFilesDictionary = new ConcurrentDictionary<int, String>();
    
                        #region Calculate ranges
    
                        var readRanges = new List<Range>();
                        for (var chunk = 0; chunk < totalThreads - 1; chunk++)
                        {
                            var range = new Range
                            {
                                Start = chunk * (responseLength / totalThreads),
                                End = (chunk + 1) * (responseLength / totalThreads) - 1,
                                ChunkIndex = chunk
                            };
                            readRanges.Add(range);
                        }
    
    
                        readRanges.Add(new Range
                        {
                            Start = readRanges.Any() ? readRanges.Last().End + 1 : 0,
                            End = responseLength - 1,
                            ChunkIndex = readRanges.Count + 1
                        });
    
                        #endregion
    
                        var startTime = DateTime.Now;
    
                        #region Parallel download
    
                        Parallel.ForEach(readRanges, new ParallelOptions {MaxDegreeOfParallelism = totalThreads}, readRange =>
                        {
                            var httpWebRequest = WebRequest.Create(fileUrl) as HttpWebRequest;
                            //  httpWebRequest.Referer = "https://ok.ru";
                            //  httpWebRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36";
                            //   httpWebRequest.Headers.Add("Origin", "https://ok.ru");
                            httpWebRequest.Method = "GET";
                            httpWebRequest.AddRange(readRange.Start, readRange.End);
    
                            using var httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
                            var tempFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".tmp");
                            using var fileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.Write);
                            httpWebResponse.GetResponseStream().CopyTo(fileStream);
    
                            lock ("Downloader.Events")
                            {
                                result.Progress += fileStream.Length;
                                var percent = 1.0 * result.Progress / result.Size;
                                Console.WriteLine("Progress: " + percent);
                            }
                           
                            fileStream.Dispose();
                            tempFilesDictionary.TryAdd(readRange.ChunkIndex, tempFilePath);
                        });
    
                        result.ParallelDownloads = totalThreads;
    
                        #endregion
    
                        result.TimeTaken = DateTime.Now.Subtract(startTime);
    
                        #region Merge to single file
    
                        foreach (var tempFile in tempFilesDictionary.OrderBy(b => b.Key))
                        {
                            lock (destinationStream)
                            {
                                Console.WriteLine($"tempFile : {tempFile.Key}");
                                var tempFileBytes = File.ReadAllBytes(tempFile.Value);
                                destinationStream.Write(tempFileBytes, 0, tempFileBytes.Length);
                                File.Delete(tempFile.Value);
                            }
                        }
    
                        #endregion
    
                        return result;
                    }
                }
            }
        }
    }
     
    catd3vjl, money and dev9x like this.
  2. dev9x

    dev9x Sơ Nhập Giang Hồ

    đc rồi nha bác. bác nhiệt tình quá. Thank bác. ko biết bác có gia đình chưa để em lì xì con bác :d
     
    firefox likes this.
  3. firefox

    firefox Bang Chúng

    thôi, không cần đâu. Ae giúp nhau được tới đâu hay tới đó. Mình cũng chỉ là dev vào đây hóng hớt thôi, hehe. Chào bác nhé
     
    Nai and dev9x like this.
  4. Hoa Mãn Lâu

    Hoa Mãn Lâu Trưởng Môn

    Cụ @firefox code đỉnh vãi xoài. :3
     
    dev9x likes this.