using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using System.Web;
using WS;
using WS.Http;
using WS.IO;
using WS.IO.Zip;

namespace QM.KJGH.CGGL.NMCGHJ
{
    public class ApiHelper
    {
        /// <summary>
        /// 格式化URL参数
        /// </summary>
        /// <param name="param">参数</param>
        /// <param name="url">url</param>
        public static string FormatUrlParam(Dictionary<string, string> param, string url = null)
        {
            var strPar = param.Keys.Select(k => { return $"{k}={param[k]}"; }).Join("&");
            if (!string.IsNullOrWhiteSpace(url))
            {
                strPar = url + (url.IndexOf("?") >= 0 ? "&" : "?") + strPar;
            }
            return strPar;
        }

        /// <summary>
        /// 获取response header中Content-Disposition中的filename值 
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        private static string GetFileName(HttpWebResponse response)
        {
            var contentHeader = response.Headers["Content-Disposition"];
            string filename = null;
            if (contentHeader != null)
            {
                filename = contentHeader.Split("filename=")[1].Trim();
                if (filename.Contains("filename*=UTF-8''"))
                {
                    filename = filename.Split("filename*=UTF-8''")[1].Trim();
                }
                WS.Log.RunLog.Debug("HESD:" + filename); 
                WS.Log.RunLog.Debug("HESD:" + HttpUtility.UrlDecode(filename));
                filename = HttpUtility.UrlDecode(filename);
            }
            return filename;
        }

        /// <summary>
        /// multipart/form-data上传文件
        /// </summary>
        /// <param name="url">请求的url地址</param>
        /// <param name="postDict">post参数</param>
        /// <param name="fileName">文件名</param>
        /// <param name="file">文件</param>
        /// <param name="fileKeyName">文件这一项参数的key</param>
        /// <param name="timeOut">超时间隔_秒</param>
        /// <returns>失败返回null</returns>
        public static string HttpPostData(string url, Dictionary<string,string> postDict,
                            string fileName, string filePath, string token, string fileKeyName = "file", int timeOut = 120)
        {

            System.GC.Collect();//垃圾回收,回收没有正常关闭的http连接

            timeOut = timeOut * 1000;
            string responseContent;

            MemoryStream memStream = null;
            Stream requestStream = null;
            HttpWebResponse httpWebResponse = null;
            HttpWebRequest webRequest = null;

            try
            {
                memStream = new MemoryStream();
                webRequest = (HttpWebRequest)WebRequest.Create(url);
                // 边界符  
                var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
                // 边界符  
                var beginBoundary = Encoding.UTF8.GetBytes("--" + boundary + "\r\n");
                // 最后的结束符  
                var endBoundary = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");

                // 设置属性  
                webRequest.Method = "POST";
                webRequest.Timeout = timeOut;
                webRequest.ContentType = "multipart/form-data; boundary=" + boundary;

                webRequest.Headers.Add("Authorization", token);

                // 写入字符串的Key  
                var stringKeyHeader = "--" + boundary +
                                        "\r\nContent-Disposition: form-data; name=\"{0}\"" +
                                        "\r\n\r\n{1}\r\n";

                if(postDict != null)
                foreach (byte[] formitembytes in from string key in postDict.Keys
                                                 select string.Format(stringKeyHeader, key, postDict[key])
                                                        into formitem
                                                 select Encoding.UTF8.GetBytes(formitem))
                {
                    memStream.Write(formitembytes, 0, formitembytes.Length);
                }

                // 写入文件  
                const string filePartHeader =
                    "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
                        "Content-Type: application/octet-stream\r\n\r\n";
                var header = string.Format(filePartHeader, fileKeyName, fileName);
                var headerbytes = Encoding.UTF8.GetBytes(header);

                memStream.Write(beginBoundary, 0, beginBoundary.Length);
                memStream.Write(headerbytes, 0, headerbytes.Length);

                var buffer = new byte[1024];
                int bytesRead; // =0  

                var file = new FileStream(filePath, FileMode.Open, FileAccess.Read);

                file.Seek(0, SeekOrigin.Begin);
                while ((bytesRead = file.Read(buffer, 0, buffer.Length)) != 0)
                {
                    memStream.Write(buffer, 0, bytesRead);
                }
                file.Close();
                file.Dispose();

                // 写入换行  
                var contentLine = Encoding.ASCII.GetBytes("\r\n");
                memStream.Write(contentLine, 0, contentLine.Length);

                // 写入最后的结束边界符  
                memStream.Write(endBoundary, 0, endBoundary.Length);

                webRequest.ContentLength = memStream.Length;

                requestStream = webRequest.GetRequestStream();

                memStream.Position = 0;
                var tempBuffer = new byte[memStream.Length];
                memStream.Read(tempBuffer, 0, tempBuffer.Length);
                //memStream.Close();

                requestStream.Write(tempBuffer, 0, tempBuffer.Length);
                //requestStream.Close();

                try
                {
                    httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
                }
                catch (WebException ex)
                {
                    httpWebResponse = (HttpWebResponse)ex.Response;
                }

                using (var httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(),
                                                                Encoding.GetEncoding("utf-8")))
                {
                    responseContent = httpStreamReader.ReadToEnd();
                }
            }
            finally
            {
                if (memStream != null) { memStream.Close(); }
                if (requestStream != null) { requestStream.Close(); }
                if (httpWebResponse != null) { httpWebResponse.Close(); }
                if (webRequest != null) { webRequest.Abort(); }
            }

            return responseContent;
        }

        /// <summary>
        /// multipart/form-data上传文件(多header)
        /// </summary>
        /// <param name="url">请求的url地址</param>
        /// <param name="postDict">post参数</param>
        /// <param name="fileName">文件名</param>
        /// <param name="file">文件</param>
        /// <param name="fileKeyName">文件这一项参数的key</param>
        /// <param name="timeOut">超时间隔_秒</param>
        /// <returns>失败返回null</returns>
        public static string HttpPostDataNm2(string url, Dictionary<string, string> postDict,
                            string fileName, string filePath, Dictionary<string, string> headers, string fileKeyName = "file", int timeOut = 120)
        {
            WS.Log.RunLog.Debug($"HttpPostDataNm2:{url} = {postDict.ToJson()} = {fileName} = {filePath} = {headers.ToJson()} = {fileKeyName} = {timeOut}");

            System.GC.Collect();//垃圾回收,回收没有正常关闭的http连接

            timeOut = timeOut * 1000;
            string responseContent;

            MemoryStream memStream = null;
            Stream requestStream = null;
            HttpWebResponse httpWebResponse = null;
            HttpWebRequest webRequest = null;
            ServicePointManager.DefaultConnectionLimit = 1000;
            try
            {
                memStream = new MemoryStream();
                webRequest = (HttpWebRequest)WebRequest.Create(url);
                // 边界符  
                var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
                // 边界符  
                var beginBoundary = Encoding.UTF8.GetBytes("--" + boundary + "\r\n");
                // 最后的结束符  
                var endBoundary = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");

                // 设置属性  
                webRequest.Method = "POST";
                webRequest.Timeout = timeOut;
                webRequest.ReadWriteTimeout = timeOut;
                webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
                webRequest.KeepAlive = false;

                if (headers != null)
                {
                    foreach (var key in headers.Keys)
                    {
                        webRequest.Headers.Add(key, headers[key]);
                    }
                }

                // 写入字符串的Key  
                var stringKeyHeader = "--" + boundary +
                                        "\r\nContent-Disposition: form-data; name=\"{0}\"" +
                                        "\r\n\r\n{1}\r\n";

                if (postDict != null)
                    foreach (byte[] formitembytes in from string key in postDict.Keys
                                                     select string.Format(stringKeyHeader, key, postDict[key])
                                                            into formitem
                                                     select Encoding.UTF8.GetBytes(formitem))
                    {
                        memStream.Write(formitembytes, 0, formitembytes.Length);
                    }

                // 写入文件  
                const string filePartHeader =
                    "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
                        "Content-Type: application/octet-stream\r\n\r\n";
                var header = string.Format(filePartHeader, fileKeyName, fileName);
                var headerbytes = Encoding.UTF8.GetBytes(header);

                memStream.Write(beginBoundary, 0, beginBoundary.Length);
                memStream.Write(headerbytes, 0, headerbytes.Length);

                var buffer = new byte[1024];
                int bytesRead; // =0  

                var file = new FileStream(filePath, FileMode.Open, FileAccess.Read);

                WS.Log.RunLog.Debug($"文件是空的吗:{file == null}");
                file.Seek(0, SeekOrigin.Begin);
                while ((bytesRead = file.Read(buffer, 0, buffer.Length)) != 0)
                {
                    memStream.Write(buffer, 0, bytesRead);
                }
                file.Close();
                file.Dispose();
                // 写入换行  
                var contentLine = Encoding.ASCII.GetBytes("\r\n");
                memStream.Write(contentLine, 0, contentLine.Length);

                // 写入最后的结束边界符  
                memStream.Write(endBoundary, 0, endBoundary.Length);

                webRequest.ContentLength = memStream.Length;

                requestStream = webRequest.GetRequestStream();

                memStream.Position = 0;
                var tempBuffer = new byte[memStream.Length];
                memStream.Read(tempBuffer, 0, tempBuffer.Length);
                //memStream.Close();
                requestStream.Write(tempBuffer, 0, tempBuffer.Length);
                //requestStream.Close();
                WS.Log.RunLog.Debug($"222222222222");
                var ermsg = string.Empty;
                try
                {
                    #region 鄂尔多斯
                    //TODO 鄂尔多斯上传有时候等不到回复,网上查加这个,试试
                    //http://t.zoukankan.com/lansehai-p-5938440.html
                    //webRequest.ServicePoint.Expect100Continue = false;
                    //ServicePointManager.Expect100Continue = false;
                    #endregion

                    httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
                }
                catch (WebException ex)
                {
                    WS.Log.RunLog.Error( ex, $"HttpWebResponse异常");
                    httpWebResponse = (HttpWebResponse)ex.Response;
                }
                WS.Log.RunLog.Debug($"HttpWebResponse是空吗?  {httpWebResponse == null}");
                if(httpWebResponse != null)
                {
                    WS.Log.RunLog.Debug($"Response => {httpWebResponse.ToJson()}");
                }
                using (var httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(),
                                                                Encoding.GetEncoding("utf-8")))
                {
                    WS.Log.RunLog.Debug($"HttpStreamReader是空吗?  {httpStreamReader == null}");
                    responseContent = httpStreamReader.ReadToEnd();
                }
            }
            finally
            {
                try
                {
                    if (memStream != null) { memStream.Close(); memStream.Dispose(); memStream = null; }
                }
                catch (Exception ex)
                {
                    WS.Log.RunLog.Error(ex, $"关闭 MemoryStream");
                }

                try
                {
                    if (requestStream != null) { requestStream.Close(); requestStream.Dispose(); requestStream = null; }
                }
                catch (Exception ex)
                {
                    WS.Log.RunLog.Error(ex, $"关闭 RequestStream");
                }

                try
                {
                    if (httpWebResponse != null) { httpWebResponse.Close(); httpWebResponse.Dispose(); httpWebResponse = null; }
                }
                catch (Exception ex)
                {
                    WS.Log.RunLog.Error(ex, $"关闭 HttpWebResponse");
                }

                try
                {
                    if (webRequest != null) { webRequest.Abort(); webRequest = null; }
                }
                catch (Exception ex)
                {
                    WS.Log.RunLog.Error(ex, $"关闭 HttpWebRequest");
                }
                System.GC.Collect();//垃圾回收,回收没有正常关闭的http连接
            }

            return responseContent;
        }


        /// <summary>
        /// 使用HttpClient上传
        /// </summary>
        /// <param name="url">请求的url地址</param>
        /// <param name="postDict">post参数</param>
        /// <param name="fileName">文件名</param>
        /// <param name="file">文件</param>
        /// <param name="fileKeyName">文件这一项参数的key</param>
        /// <param name="timeOut">超时间隔_秒</param>
        /// <returns></returns>
        public static string HttpClientPost(string url, Dictionary<string, string> postDict,
                            string fileName, string filePath, Dictionary<string, string> headers, string fileKeyName = "file", int timeOut = 120)
        {

            //执行代码
            using (HttpClient client = new HttpClient())
            {
                var content = new MultipartFormDataContent();
                //头
                if (headers != null)
                {
                    foreach (var key in headers.Keys)
                    {
                        client.DefaultRequestHeaders.Add(key, headers[key]);
                    }
                }
                //添加字符串参数
                if (postDict != null)
                {
                    foreach (var key in postDict.Keys)
                    {
                        if (postDict[key] != null)
                            content.Add(new StringContent(postDict[key]), key);
                    }
                }
                client.Timeout = TimeSpan.FromSeconds(timeOut);

                //添加文件参数,参数名为files,文件名为123.png
                content.Add(new ByteArrayContent(System.IO.File.ReadAllBytes(filePath)), fileKeyName, fileName);
                WS.Log.RunLog.Debug($"开始上传");

                var result = "";
                var task = Task.Factory.StartNew(() =>
                {
                    result = client.PostAsync(url, content).Result.Content.ReadAsStringAsync().Result;
                    WS.Log.RunLog.Debug($"新文件上传返回:" + result);
                });
                if (!task.Wait(TimeSpan.FromSeconds(timeOut)))
                {
                    WS.Log.RunLog.Debug($"文件上传无返回超时");
                    result = "{\"code\":999,\"success\":true,\"data\":{},\"msg\":\"文件上传无返回超时[{"+ timeOut + "}]!\"}";
                    try
                    {
                        client.Dispose();
                    }
                    catch (Exception ex )
                    {
                        WS.Log.RunLog.Debug($"手动释放。。。"+ex.Message);
                    }
                }
                return result;
            }
        }

        /// <summary>
        /// 上传文件,分片好用
        /// multipart/form-data上传文件
        /// </summary>
        /// <param name="url">请求的url地址</param>
        /// <param name="files">上传文件<name,文件路径></param>
        /// <param name="postData">post参数<key,value></param>
        /// <param name="urlParam">url参数<key,value></param>
        /// <param name="timeOut">超时间隔_秒</param>
        /// <returns>失败返回null</returns>
        public static string HttpPostFormdata(
            string url, 
            Dictionary<string, string> urlParam = null,
            Dictionary<string, string> postData = null,
            Dictionary<string, string> files = null,
            Dictionary<string, string> headers = null,
            int timeOut = 120)
        {

            GC.Collect();//垃圾回收,回收没有正常关闭的http连接

            timeOut = timeOut * 1000;
            string responseContent;

            MemoryStream memStream = null;
            Stream requestStream = null;
            HttpWebResponse httpWebResponse = null;
            HttpWebRequest webRequest = null;
            try
            {
                memStream = new MemoryStream();
                #region URL参数
                if (urlParam != null && urlParam.Count > 0)
                {
                    url = FormatUrlParam(urlParam, url);
                }
                #endregion
                // 边界符  
                var boundary = $"---------------{DateTime.Now.Ticks.ToString("x")}";
                // 边界符  
                var beginBoundary = Encoding.UTF8.GetBytes($"--{boundary}\r\n");
                // 最后的结束符  
                var endBoundary = Encoding.UTF8.GetBytes($"--{boundary}--\r\n");

                // 设置属性  
                webRequest = (HttpWebRequest)WebRequest.Create(url);
                webRequest.Method = "POST";
                webRequest.Timeout = timeOut;
                webRequest.ContentType = $"multipart/form-data; boundary={boundary}";

                #region Headers
                if (headers != null && headers.Count > 0)
                {
                    foreach (var key in headers.Keys)
                    {
                        webRequest.Headers.Add(key, headers[key]);
                    }
                }
                #endregion

                #region body参数
                var stringKeyHeader = $"--{boundary}" + "\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n";
                if (postData != null && postData.Count > 0)
                    foreach (byte[] formitembytes in from string key in postData.Keys
                                                     select string.Format(stringKeyHeader, key, postData[key])
                                                            into formitem
                                                     select Encoding.UTF8.GetBytes(formitem))
                    {
                        memStream.Write(formitembytes, 0, formitembytes.Length);
                    }
                #endregion

                #region 文件
                if (files != null && files.Count > 0)
                {
                    foreach (var key in files.Keys)
                    {
                        const string filePartHeader = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n"
                            + "Content-Type: application/octet-stream\r\n\r\n";
                        var header = string.Format(filePartHeader, key, Path.GetFileName(files[key]));
                        var headerbytes = Encoding.UTF8.GetBytes(header);
                        memStream.Write(beginBoundary, 0, beginBoundary.Length);
                        memStream.Write(headerbytes, 0, headerbytes.Length);

                        var buffer = new byte[1024];
                        int bytesRead; // =0  

                        var file = new FileStream(files[key], FileMode.Open, FileAccess.Read);

                        file.Seek(0, SeekOrigin.Begin);
                        while ((bytesRead = file.Read(buffer, 0, buffer.Length)) != 0)
                        {
                            memStream.Write(buffer, 0, bytesRead);
                        }
                        file.Close();
                        file.Dispose();
                        // 写入换行  
                        var contentLine = Encoding.ASCII.GetBytes("\r\n");
                        memStream.Write(contentLine, 0, contentLine.Length);
                    }
                }
                #endregion

                // 写入最后的结束边界符  
                memStream.Write(endBoundary, 0, endBoundary.Length);
                webRequest.ContentLength = memStream.Length;
                requestStream = webRequest.GetRequestStream();

                memStream.Position = 0;
                var tempBuffer = new byte[memStream.Length];
                memStream.Read(tempBuffer, 0, tempBuffer.Length);

                requestStream.Write(tempBuffer, 0, tempBuffer.Length);
                try
                {
                    httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
                }
                catch (WebException ex)
                {
                    httpWebResponse = (HttpWebResponse)ex.Response;
                }

                using (var httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.GetEncoding("utf-8")))
                {
                    responseContent = httpStreamReader.ReadToEnd();
                }
            }
            finally
            {
                if (memStream != null) { memStream.Close(); }
                if (requestStream != null) { requestStream.Close(); }
                if (httpWebResponse != null) { httpWebResponse.Close(); }
                if (webRequest != null) { webRequest.Abort(); }
            }
            return responseContent;
        }

        /// <summary>
        /// 上传文件,分片好用
        /// multipart/form-data上传文件
        /// </summary>
        /// <param name="url">请求的url地址</param>
        /// <param name="files">上传文件<name,文件路径></param>
        /// <param name="postData">post参数<key,value></param>
        /// <param name="urlParam">url参数<key,value></param>
        /// <param name="timeOut">超时间隔_秒</param>
        /// <returns>失败返回null</returns>
        public static string HttpGetFormdata(
            string url,
            Dictionary<string, string> urlParam = null,
            Dictionary<string, string> postData = null,
            Dictionary<string, string> files = null,
            Dictionary<string, string> headers = null,
            int timeOut = 120)
        {

            GC.Collect();//垃圾回收,回收没有正常关闭的http连接

            timeOut = timeOut * 1000;
            string responseContent;

            MemoryStream memStream = null;
            Stream requestStream = null;
            HttpWebResponse httpWebResponse = null;
            HttpWebRequest webRequest = null;
            try
            {
                memStream = new MemoryStream();
                #region URL参数
                if (urlParam != null && urlParam.Count > 0)
                {
                    url = FormatUrlParam(urlParam, url);
                }
                #endregion
                // 边界符  
                var boundary = $"---------------{DateTime.Now.Ticks.ToString("x")}";
                // 边界符  
                var beginBoundary = Encoding.UTF8.GetBytes($"--{boundary}\r\n");
                // 最后的结束符  
                var endBoundary = Encoding.UTF8.GetBytes($"--{boundary}--\r\n");

                // 设置属性  
                webRequest = (HttpWebRequest)WebRequest.Create(url);
                webRequest.Method = "GET";
                webRequest.Timeout = timeOut;
                webRequest.ContentType = $"multipart/form-data; boundary={boundary}";

                #region Headers
                if (headers != null && headers.Count > 0)
                {
                    foreach (var key in headers.Keys)
                    {
                        webRequest.Headers.Add(key, headers[key]);
                    }
                }
                #endregion

                #region body参数
                var stringKeyHeader = $"--{boundary}" + "\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n";
                if (postData != null && postData.Count > 0)
                    foreach (byte[] formitembytes in from string key in postData.Keys
                                                     select string.Format(stringKeyHeader, key, postData[key])
                                                            into formitem
                                                     select Encoding.UTF8.GetBytes(formitem))
                    {
                        memStream.Write(formitembytes, 0, formitembytes.Length);
                    }
                #endregion

                #region 文件
                if (files != null && files.Count > 0)
                {
                    foreach (var key in files.Keys)
                    {
                        const string filePartHeader = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n"
                            + "Content-Type: application/octet-stream\r\n\r\n";
                        var header = string.Format(filePartHeader, key, Path.GetFileName(files[key]));
                        var headerbytes = Encoding.UTF8.GetBytes(header);
                        memStream.Write(beginBoundary, 0, beginBoundary.Length);
                        memStream.Write(headerbytes, 0, headerbytes.Length);

                        var buffer = new byte[1024];
                        int bytesRead; // =0  

                        var file = new FileStream(files[key], FileMode.Open, FileAccess.Read);

                        file.Seek(0, SeekOrigin.Begin);
                        while ((bytesRead = file.Read(buffer, 0, buffer.Length)) != 0)
                        {
                            memStream.Write(buffer, 0, bytesRead);
                        }
                        file.Close();
                        file.Dispose();
                        // 写入换行  
                        var contentLine = Encoding.ASCII.GetBytes("\r\n");
                        memStream.Write(contentLine, 0, contentLine.Length);
                    }
                }
                #endregion

                // 写入最后的结束边界符  
                memStream.Write(endBoundary, 0, endBoundary.Length);
                webRequest.ContentLength = memStream.Length;
                requestStream = webRequest.GetRequestStream();

                memStream.Position = 0;
                var tempBuffer = new byte[memStream.Length];
                memStream.Read(tempBuffer, 0, tempBuffer.Length);

                requestStream.Write(tempBuffer, 0, tempBuffer.Length);
                try
                {
                    httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
                }
                catch (WebException ex)
                {
                    httpWebResponse = (HttpWebResponse)ex.Response;
                }

                using (var httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.GetEncoding("utf-8")))
                {
                    responseContent = httpStreamReader.ReadToEnd();
                }
            }
            finally
            {
                if (memStream != null) { memStream.Close(); }
                if (requestStream != null) { requestStream.Close(); }
                if (httpWebResponse != null) { httpWebResponse.Close(); }
                if (webRequest != null) { webRequest.Abort(); }
            }
            return responseContent;
        }


        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="savePath"></param>
        /// <param name="headers"></param>
        public static string HttpDownFile(string url, string savePath, Dictionary<string, string> headers = null, int timeOut = 120)
        {
            timeOut = timeOut * 1000;
            byte[] fileBytes;
            string file = string.Empty;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.Timeout = timeOut;
            if (headers != null)
            {
                foreach (var key in headers.Keys)
                {
                    request.Headers.Add(key, headers[key]);
                }
            }
            using (WebResponse webRes = request.GetResponse())
            {
                int length = (int)webRes.ContentLength;
                HttpWebResponse response = webRes as HttpWebResponse;
                file = Path.Combine(savePath, GetFileName(response));
                Stream stream = response.GetResponseStream();
                //读取到内存
                MemoryStream stmMemory = new MemoryStream();
                byte[] buffer = new byte[length];
                int i;
                //将字节逐个放入到Byte中
                while ((i = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    stmMemory.Write(buffer, 0, i);
                }
                fileBytes = stmMemory.ToArray();//文件流Byte
                FileStream fs = new FileStream(file, FileMode.OpenOrCreate);
                stmMemory.WriteTo(fs);
                stmMemory.Close();
                fs.Close();
            }
            return file;
        }

        /// <summary>
        /// 获取文件MD5值
        /// </summary>
        /// <param name="file">文件绝对路径</param>
        /// <returns>MD5值</returns>
        public static string GetMD5HashFromFile(string file)
        {
            try
            {
                FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
                System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(fileStream);
                fileStream.Close();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new UseMassageException("获取文件MD5值error:" + ex.Message);
            }
        }


        /// <summary>
        /// 合并
        /// </summary>
        /// <param name="finalFile">最终的文件名</param>
        /// <param name="fpList">分包</param>
        /// <returns></returns>
        public static string FileMerge(string finalFile, Dictionary<int,string> fpList, bool delfp = false)
        {
            if (File.Exists(finalFile)) File.Delete(finalFile);
            var errorMsg = new List<string>();
            //验证文件逻辑
            var index = 0;
            var files = new List<string>();
            foreach (var chunk in fpList.Keys)
            {
                if (index == 0) index = chunk;
                else if (chunk != index)
                {
                    throw new UseMassageException($"缺少分片文件({chunk}),调用【检查文件分片信息接口(/api/open/results/md5)】检查已上传分包");
                }
                fpList[chunk] = FileManage.Instance.ToFullPath(fpList[chunk], false);
                if (!File.Exists(fpList[chunk]))
                {
                    errorMsg.Add(chunk.ToString());
                }
                index++;
                files.Add(fpList[chunk]);
            }
            if (errorMsg.Count > 0)
            {
                throw new UseMassageException($"未接收到分片{errorMsg.Join("、")}的文件,请重新上传");
            }

            //文件合包
            if (fpList.Count > 1)
            {
                using (var fs = new FileStream(finalFile, FileMode.Create))
                {
                    foreach (var part in files)
                    {
                        var bytes = File.ReadAllBytes(part);
                        fs.Write(bytes, 0, bytes.Length);
                        bytes = null;
                    }
                }
            }
            else
            {
                File.Copy(files[0], finalFile);
            }
            //检查成果文件
            if (File.Exists(finalFile))
            {
                if (delfp)
                {
                    foreach (var part in files)
                    {
                        try
                        {
                            File.Delete(part);//删除分块
                        }
                        catch (Exception)
                        { }
                    }
                }
            }
            else
            {
                throw new UseMassageException($"合包失败,请联系管理员");
            }
            //解压
            return WinRAR.UnRarOrZip(finalFile);
        }


        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="savePath"></param>
        /// <param name="headers"></param>
        public static string HttpDownFilePost(string url, string savePath, Dictionary<string, string> headers = null, int timeOut = 120)
        {
            timeOut = timeOut * 1000;
            byte[] fileBytes;
            string file = string.Empty;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.Timeout = timeOut;
            if (headers != null)
            {
                foreach (var key in headers.Keys)
                {
                    request.Headers.Add(key, headers[key]);
                }
            }
            WS.Log.RunLog.Debug($"准备下载文件:" + url);
            using (WebResponse webRes = request.GetResponse())
            {
                try
                {
                    WS.Log.RunLog.Debug($"下载返回:" + webRes.ToJson());
                    int length = (int)webRes.ContentLength;
                    WS.Log.RunLog.Debug($"下载文件大小:" + length);
                    HttpWebResponse response = webRes as HttpWebResponse;
                    file = Path.Combine(savePath, GetFileName(response));
                    WS.Log.RunLog.Debug($"下载文件路径:" + file);
                    Stream stream = response.GetResponseStream();
                    //读取到内存
                    MemoryStream stmMemory = new MemoryStream();
                    byte[] buffer = new byte[length];
                    int i;
                    //将字节逐个放入到Byte中
                    while ((i = stream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        stmMemory.Write(buffer, 0, i);
                    }
                    fileBytes = stmMemory.ToArray();//文件流Byte
                    FileStream fs = new FileStream(file, FileMode.OpenOrCreate);
                    stmMemory.WriteTo(fs);
                    stmMemory.Close();
                    fs.Close();
                }
                catch (Exception ex)
                {
                    WS.Log.RunLog.Error(ex, $"下载文件异常:" + ex.Message);
                    throw;
                }
            }
            return file;
        }



        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="savePath"></param>
        /// <param name="headers"></param>
        public static string HttpDownFileOrDataPost(string url, string savePath, Dictionary<string, string> headers = null, int timeOut = 120)
        {
            timeOut = timeOut * 1000;
            byte[] fileBytes;
            string file = string.Empty;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.Timeout = timeOut;
            if (headers != null)
            {
                foreach (var key in headers.Keys)
                {
                    request.Headers.Add(key, headers[key]);
                }
            }
            WS.Log.RunLog.Debug($"准备下载文件:" + url);
            using (WebResponse webRes = request.GetResponse())
            {
                try
                {
                    WS.Log.RunLog.Debug($"下载返回:" + webRes.ToJson());
                    int length = (int)webRes.ContentLength;
                    WS.Log.RunLog.Debug($"下载文件大小:" + length);
                    if (length < 0)
                    {
                        var res = HttpHelper.HttpPost(url, string.Empty, headers);
                        return res;
                    }
                    else
                    {
                        HttpWebResponse response = webRes as HttpWebResponse;
                        file = Path.Combine(savePath, GetFileName(response));
                        WS.Log.RunLog.Debug($"下载文件路径:" + file);
                        Stream stream = response.GetResponseStream();
                        //读取到内存
                        MemoryStream stmMemory = new MemoryStream();
                        byte[] buffer = new byte[length];
                        int i;
                        //将字节逐个放入到Byte中
                        while ((i = stream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            stmMemory.Write(buffer, 0, i);
                        }
                        fileBytes = stmMemory.ToArray();//文件流Byte
                        FileStream fs = new FileStream(file, FileMode.OpenOrCreate);
                        stmMemory.WriteTo(fs);
                        stmMemory.Close();
                        fs.Close();
                    }
                }
                catch (Exception ex)
                {
                    WS.Log.RunLog.Error(ex, $"下载文件异常:" + ex.Message);
                    throw;
                }
            }
            return file;
        }

    }
}