using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Org.BouncyCastle.Asn1.Ocsp; using PTMedicalInsurance.Common; using PTMedicalInsurance.Variables; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Security.Cryptography; using System.Security.Policy; using System.Text; using System.Threading.Tasks; namespace PTMedicalInsurance.Helper { class InvokeRestCenter : IInvokeCenter { private static string GetRandomString(int length) { const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; var random = new Random(); return new string(Enumerable.Repeat(chars, length) .Select(s => s[random.Next(s.Length)]).ToArray()); } private static long GetCurrentUnixSeconds() { DateTimeOffset utcNow = DateTimeOffset.UtcNow.AddHours(8); return (long)(utcNow.ToUniversalTime().DateTime.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))).TotalSeconds; } private static string GetSHA256Str(string input) { using (SHA256 sha256Hash = SHA256.Create()) { byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(input)); StringBuilder builder = new StringBuilder(); foreach (byte b in bytes) { builder.Append(b.ToString("x2")); } return builder.ToString(); } } public int Business(string inputData, ref string outputData, ref string pErrMsg) { outputData = ""; pErrMsg = ""; JObject joRtn = new JObject(); try { if (string.IsNullOrEmpty(Global.curEvt.URL)) { Global.curEvt.URL = Global.inf.centerURL; } //创建一个HTTP请求 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Global.curEvt.URL); //Post请求方式 request.Method = "POST"; //设置头部信息 string headstr = @"Bearer " + Global.curEvt.token;//市医保token request.Headers.Add("Authorization", headstr); //内容类型 request.ContentType = "application/json"; //设置参数,并进行URL编码 string paraUrlCoded = inputData;//System.Web.HttpUtility.UrlEncode(jsonParas); byte[] payload; //将Json字符串转化为字节 payload = System.Text.Encoding.UTF8.GetBytes(paraUrlCoded); //设置请求的ContentLength request.ContentLength = payload.Length; //发送请求,获得请求流 Stream writer; writer = request.GetRequestStream();//获取用于写入请求数据的Stream对象 //将请求参数写入流 writer.Write(payload, 0, payload.Length); writer.Close();//关闭请求流 HttpWebResponse response = null; try { //获得响应流 response = (HttpWebResponse)request.GetResponse(); } catch (WebException ex) { HttpWebResponse res = (HttpWebResponse)ex.Response; Stream myResponseStream = res.GetResponseStream(); StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8); string retString = myStreamReader.ReadToEnd(); outputData = JsonHelper.setExceptionJson(-99, "异常返回", retString).ToString(); return -1; } outputData = getResponseData(response); joRtn = JObject.Parse(outputData);//返回Json数据 if (joRtn.ContainsKey("body")) { joRtn = (JObject)joRtn.GetValue("body"); outputData = JsonHelper.toJsonString(joRtn); } return 0; } catch (Exception ex) { joRtn.Add("infcode", -1); joRtn.Add("err_msg", "调用中心服务异常invokeCenterService(1):" + ex.Message); outputData = JsonHelper.toJsonString(joRtn); return -1; } } public int BusinessExt(string inputData, ref string outputData, ref string pErrMsg) { return this.Business(inputData, ref outputData, ref pErrMsg); } //public int DownloadFile(string inputData, ref string outputData) //{ // outputData = ""; // string error = string.Empty; int errorCode = 0; // try // { // JObject jsonInParam = JObject.Parse(inputData); // // 去除外wrapper层便于通用 // Utils.removeWrapper(jsonInParam); // string fileName = (string)jsonInParam["input"]["fsDownloadIn"]["filename"]; // string filePath = Global.curEvt.path + "\\Download\\" + fileName; // //如果不存在目录,则创建目录 // if (!Directory.Exists(Global.curEvt.path + "\\Download")) // { // //创建文件夹 // DirectoryInfo dirInfo = Directory.CreateDirectory(Global.curEvt.path + "\\Download"); // } // if (File.Exists(filePath)) // { // File.Delete(filePath); // } // FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); // //创建一个HTTP请求 // HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Global.curEvt.URL); // //Post请求方式 // request.Method = "POST"; // //设置参数,并进行URL编码 // string paraUrlCoded = JsonHelper.toJsonString(jsonInParam); // byte[] payload; // //将Json字符串转化为字节 // payload = System.Text.Encoding.UTF8.GetBytes(paraUrlCoded); // //设置请求的ContentLength // request.ContentLength = payload.Length; // Stream writer; // try // { // writer = request.GetRequestStream();//获取用于写入请求数据的Stream对象 // } // catch (Exception) // { // writer = null; // errorCode = -100; // error = "连接服务器失败!"; // } // //将请求参数写入流 // writer.Write(payload, 0, payload.Length); // writer.Close();//关闭请求流 // // String strValue = "";//strValue为http响应所返回的字符流 // //发送请求并获取相应回应数据 // HttpWebResponse response = request.GetResponse() as HttpWebResponse; // //直到request.GetResponse()程序才开始向目标网页发送Post请求 // Stream responseStream = response.GetResponseStream(); // //创建本地文件写入流 // byte[] bArr = new byte[102400]; // int iTotalSize = 0; // int size = responseStream.Read(bArr, 0, (int)bArr.Length); // while (size > 0) // { // iTotalSize += size; // fs.Write(bArr, 0, size); // size = responseStream.Read(bArr, 0, (int)bArr.Length); // } // fs.Close(); // responseStream.Close(); // dynamic joReturn = new JObject(); // joReturn.errorCode = errorCode; // joReturn.errorMessage = error; // joReturn.filePath = filePath; // outputData = joReturn.ToString(); // } // catch (Exception ex) // { // errorCode = -100; // error = ex.Message; // dynamic joReturn = new JObject(); // joReturn.errorCode = errorCode; // joReturn.errorMessage = error; // outputData = joReturn.ToString(); // return -1; // } // finally // { // Global.writeLog("DownloadCenterFile" + "(" + Global.curEvt.URL + ")", inputData, outputData); // } // return 0; //} public int DownloadFile(string inputData, ref string outputData) { outputData = ""; int errorCode = 0; string error = string.Empty; string filePath = ""; HttpWebResponse response = null; FileStream fs = null; try { JObject jsonInParam = JObject.Parse(inputData); Utils.removeWrapper(jsonInParam); string fileName = (string)jsonInParam["input"]["fsDownloadIn"]["filename"]; if (string.IsNullOrWhiteSpace(fileName)) { errorCode = -101; error = "文件名不能为空"; throw new ArgumentException(error); } string downloadDir = Path.Combine(Global.curEvt.path, "Download"); filePath = Path.Combine(downloadDir, fileName); // 创建目录 if (!Directory.Exists(downloadDir)) { Directory.CreateDirectory(downloadDir); } // 删除旧文件 if (File.Exists(filePath)) { File.Delete(filePath); } // 准备 POST 请求 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Global.inf.downURL); request.Method = "POST"; request.ContentType = "application/json; charset=utf-8"; //request.UserAgent = "DownloadClient/1.0"; // 添加 Authorization 头 string headstr = @"Bearer " + Global.curEvt.token;//市医保token request.Headers.Add("Authorization", headstr); string requestBody = JsonHelper.toJsonString(jsonInParam); byte[] payload = Encoding.UTF8.GetBytes(requestBody); request.ContentLength = payload.Length; // 写入请求体 using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(payload, 0, payload.Length); } // 获取响应 response = (HttpWebResponse)request.GetResponse(); // ✅ 关键:记录状态码和 Content-Type string statusCode = $"{(int)response.StatusCode} {response.StatusCode}"; string contentType = response.ContentType?.ToLower() ?? ""; Global.writeLog("DownloadFile_Response", $"StatusCode: {statusCode}\r\n" , $"Content-Type: {contentType}"); // ✅ 判断是否可能是错误响应(即使 200 OK) bool isJsonOrError = contentType.Contains("json") || contentType.Contains("text") || response.ContentLength < 1024; // 小文件很可能是错误信息 using (Stream responseStream = response.GetResponseStream()) using (fs = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { byte[] buffer = new byte[8192]; int bytesRead; long totalBytesRead = 0; MemoryStream firstChunk = new MemoryStream(); // 仅缓存前 1KB 用于判断 while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0) { // 累计写入文件 fs.Write(buffer, 0, bytesRead); totalBytesRead += bytesRead; // ✅ 仅在开始时缓存前 1KB 用于错误判断 if (totalBytesRead <= 1024) { firstChunk.Write(buffer, 0, bytesRead); } } // 文件已完整写入磁盘,现在检查前 1KB 是否为错误信息 if (isJsonOrError || totalBytesRead < 1024) { string firstContent = Encoding.UTF8.GetString(firstChunk.ToArray()); firstContent = firstContent.Trim(); // 判断是否为 JSON 错误 if (firstContent.StartsWith("{") && (firstContent.Contains("\"code\"") || firstContent.Contains("err_msg"))) { try { var errorObj = JObject.Parse(firstContent); int? errCode = errorObj["code"]?.Value() ?? errorObj["infcode"]?.Value(); if (errCode != null && errCode != 0 && errCode != 200) { string errMsg = errorObj["err_msg"]?.Value() ?? errorObj["errorMessage"]?.Value() ?? "Unknown error"; throw new Exception($"业务错误 [{errCode}]: {errMsg}"); } } catch (JsonException) { // 不是 JSON,但内容可疑 throw new Exception("服务器返回错误内容,非有效文件: " + firstContent); } } } } // ✅ 成功:返回结果 dynamic joReturn = new JObject(); joReturn.errorCode = 0; joReturn.errorMessage = ""; joReturn.filePath = filePath; joReturn.fileSize = new FileInfo(filePath).Length; outputData = joReturn.ToString(); return 0; } catch (WebException webEx) { Global.writeLog($"进入异常 + {webEx}"); // 处理 HTTP 层错误 if (webEx.Response is HttpWebResponse errResponse) { using (var sr = new StreamReader(errResponse.GetResponseStream())) { string serverMsg = sr.ReadToEnd(); errorCode = (int)errResponse.StatusCode; error = $"请求失败 :{webEx} [{errResponse.StatusCode}]: {serverMsg}"; } } else { errorCode = -100; error = "连接服务器失败: " + webEx.Message; } } catch (JsonException jsonEx) { errorCode = -200; error = "输入数据格式错误: " + jsonEx.Message; } catch (UnauthorizedAccessException accEx) { errorCode = -300; error = "无权访问文件或目录: " + accEx.Message; } catch (IOException ioEx) { errorCode = -400; error = "文件操作失败: " + ioEx.Message; } catch (Exception ex) when (errorCode == 0) { errorCode = -999; error = "未知错误: " + ex.Message; } finally { response?.Close(); if (string.IsNullOrEmpty(outputData)) { dynamic joReturn = new JObject(); joReturn.errorCode = errorCode; joReturn.errorMessage = error; if (!string.IsNullOrEmpty(filePath)) joReturn.filePath = filePath; outputData = joReturn.ToString(); } Global.writeLog($"DownloadFile({Global.inf.downURL})", inputData, outputData); } return -1; } public void Test1(string DownInput) { HttpClient httpClient = null; HttpResponseMessage response = null; try { // 创建 HttpClient 并设置超时 var handler = new HttpClientHandler(); httpClient = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(10) // 连接 + 响应超时 }; // 构造请求内容 var content = new StringContent(DownInput, Encoding.UTF8, "text/plain"); content.Headers.ContentType = new MediaTypeHeaderValue("text/plain"); // 添加 Authorization 头 string headstr = "Bearer " + Global.curEvt.token; // 市医保 token //httpClient.DefaultRequestHeaders.Authorization = // new AuthenticationHeaderValue("Bearer", Global.curEvt.token); // 或者使用: httpClient.DefaultRequestHeaders.Add("Authorization", headstr); // 发送 POST 请求(同步等待) response = httpClient.PostAsync(Global.inf.centerURL, content).GetAwaiter().GetResult(); // 检查状态码 if (response.StatusCode != System.Net.HttpStatusCode.OK) { throw new HttpRequestException($"HTTP 请求失败,状态码: {response.StatusCode}"); } // 读取 Content-Type 判断响应类型 var contentType = response.Content.Headers.ContentType?.MediaType ?? ""; if (contentType.Contains("application/octet-stream")) { // 情况1:返回的是文件流(二进制流) using (var responseStream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult()) using (var fileStream = new FileStream("testDownload.txt", FileMode.Create, FileAccess.Write)) { responseStream.CopyTo(fileStream); } Global.writeLog("文件已下载到 testDownload.txt"); } else { // 情况2:返回的是字符串(如 JSON) string result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); Global.writeLog("Test1:" + result); } } catch (AggregateException ax) when (ax.InnerException is TimeoutException) { throw new TimeoutException("请求超时", ax.InnerException); } catch (HttpRequestException e) { throw new Exception("HTTP 请求异常: " + e.Message, e); } catch (Exception e) { throw new Exception("发生未知错误: " + e.Message, e); } finally { // 手动释放资源 response?.Dispose(); httpClient?.Dispose(); } } public int Init(ref string pErrMsg) { return 0; } public int UploadFile(string inputData, ref string outputData, ref string pErrMsg) { throw new NotImplementedException(); } private string getResponseData(HttpWebResponse response) { string data = ""; if (response != null) { Stream s = response.GetResponseStream(); StreamReader sRead = new StreamReader(s,Encoding.GetEncoding("UTF-8")); data = sRead.ReadToEnd(); sRead.Close(); response.Close(); } return data; } } }