HttpExt.cs 8.81 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Install.Core.Common
{
    public class HttpExt
    {
        /// <summary>
        /// http下载文件
        /// </summary>
        /// <param name="url">下载文件地址</param>
        /// <returns></returns>
        public static byte[] HttpDownload(string url)
        {
            try
            {
                MemoryStream fs = new MemoryStream();
                // 设置参数
                HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
                //发送请求并获取相应回应数据
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                //直到request.GetResponse()程序才开始向目标网页发送Post请求
                Stream responseStream = response.GetResponseStream();
                //创建本地文件写入流
                long totalSize = response.ContentLength;
                int postion = 0;
                byte[] bArr = new byte[1024];
                int size = responseStream.Read(bArr, 0, (int)bArr.Length);

                while (size > 0)
                {
                    postion += size;

                    fs.Write(bArr, 0, size);
                    size = responseStream.Read(bArr, 0, (int)bArr.Length);

                }
                Console.WriteLine();
                //stream.Close();
                fs.Close();
                responseStream.Close();

                return fs.ToArray();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="url">下载的路径</param>
        /// <param name="path">下载到的本地位置</param>
        /// <param name="md5">md5</param>
        /// <param name="totalSizeChanged">文件总大小 byte</param>
        /// <param name="currSizeChanged">已经下载大小 byte</param>
        /// <param name="speedChanged">下载速度 byte/s</param>
        /// <param name="elapsedTimeSecChanged">已经消耗的秒数</param>
        /// <param name="remainingTimeSecChanged">预计剩余秒数</param>
        /// <returns></returns>
        public static bool BreakpointDownload(
            string url, string path, string md5,
            Action<long> totalSizeChanged = null,
            Action<long> currSizeChanged = null,
            Action<long> speedChanged = null,
            Action<int> elapsedTimeSecChanged = null,
            Action<int> remainingTimeSecChanged = null)
        {
            //1.下载 md5 文件
            string path_md5 = $"{path}.md5";

            if (File.Exists(path_md5))
            {
                //获取本地 md5
                StreamReader sr = new StreamReader(path_md5, System.Text.Encoding.UTF8);
                string localMd5 = sr.ReadLine();
                localMd5 = localMd5.Trim();
                sr.Close();

                //2. 检测 下载回来的md5 与 本地的md5 是否一致, 一致则断点下载
                if (md5 == localMd5)
                {
                    //相同, 继续下载
                    bool ret = BreakpointDownload(url, path, false, totalSizeChanged, currSizeChanged, speedChanged, elapsedTimeSecChanged, remainingTimeSecChanged);
                    if (ret == true)
                    {
                        //下载完了
                        //把本地的 md5 文件删除
                        File.Delete(path_md5);
                    }
                    return ret;
                } 
            }


            {
                //没有本地 md5 信息,创建
                //保存到 filePath.md5
                StreamWriter sw = new StreamWriter(path_md5, false, System.Text.Encoding.UTF8);
                sw.WriteLine(md5);
                sw.Flush();
                sw.Close();

                //重新下载
                return BreakpointDownload(url, path, true, totalSizeChanged, currSizeChanged, speedChanged, elapsedTimeSecChanged, remainingTimeSecChanged);
            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="url">下载的路径</param>
        /// <param name="path">下载到的本地位置</param>
        /// <param name="isRedownload">重新下载?</param>
        /// <param name="totalSizeChanged">文件总大小 byte</param>
        /// <param name="currSizeChanged">已经下载大小 byte</param>
        /// <param name="speedChanged">下载速度 byte/s</param>
        /// <param name="elapsedTimeSecChanged">已经消耗的秒数</param>
        /// <param name="remainingTimeSecChanged">预计剩余秒数</param>
        /// <returns></returns>
        public static bool BreakpointDownload(
            string url, string path, bool isRedownload=false,
            Action<long> totalSizeChanged = null,
            Action<long> currSizeChanged =null,
            Action<long> speedChanged = null,
            Action<int> elapsedTimeSecChanged = null,
            Action<int> remainingTimeSecChanged = null)
        {
            string tempPath = System.IO.Path.GetDirectoryName(path);// + @"\temp";
            if (!string.IsNullOrEmpty(tempPath))
            {
                //先新建文件夹
                if(!System.IO.Directory.Exists(tempPath))
                    System.IO.Directory.CreateDirectory(tempPath);
                tempPath += @"\";
            }
            //System.IO.Directory.CreateDirectory(tempPath);  //创建临时文件目录
            string tempFile = $@"{tempPath}{System.IO.Path.GetFileName(path)}.temp"; //临时文件

            if (isRedownload)
            {
                if (System.IO.File.Exists(path))
                {
                    System.IO.File.Delete(path);    //存在则删除
                }
                //重新下载
                if (System.IO.File.Exists(tempFile))
                {
                    System.IO.File.Delete(tempFile);    //存在则删除
                }
            }
            else {
                if (System.IO.File.Exists(path))
                    return true;//已经下载过了
            }

            try
            {
                //FileStream fs = new FileStream(tempFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
                // 设置参数
                HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

                FileStream fs = new FileStream(tempFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);

                request.AddRange(Convert.ToInt32(fs.Length));//接上次下载的字节开始下载文件   

                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                int elapsedTimeSec = 0;
                //发送请求并获取相应回应数据
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                //直到request.GetResponse()程序才开始向目标网页发送Post请求
                Stream responseStream = response.GetResponseStream();

                long downloadSize = 0;
                long currSize = fs.Length;
                long totalSize = response.ContentLength + currSize;
                currSizeChanged?.Invoke(currSize);
                totalSizeChanged?.Invoke(totalSize);
                
                do {
                    byte[] bArr = new byte[1024];
                    int size = responseStream.Read(bArr, 0, (int)bArr.Length);
                    if (size <= 0)
                        break;//没有数据。。。。
                    currSize += size;
                    currSizeChanged?.Invoke(currSize);

                    downloadSize += size;
                    if (elapsedTimeSec != (int)stopwatch.Elapsed.TotalSeconds) {

                        elapsedTimeSec = (int)stopwatch.Elapsed.TotalSeconds;
                        elapsedTimeSecChanged?.Invoke(elapsedTimeSec);
                        //过了1秒
                        long speed = (long)(downloadSize / stopwatch.Elapsed.TotalSeconds);
                        speedChanged?.Invoke(speed);

                        //更新剩余时间
                        int remainingTimeSec = (int)((totalSize - currSize) / speed);
                        remainingTimeSecChanged?.Invoke(remainingTimeSec);
                    }

                    fs.Write(bArr, 0, size);
                } while (true);

                fs.Close();
                responseStream.Close();

                //把临时文件,重命名
                System.IO.File.Move(tempFile, path);
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}