geboshi_V1/LeatherProject/ServerApp/WebServer/WebService.cs

636 lines
29 KiB
C#
Raw Normal View History

using Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Service;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ServerApp.WebServer
{
public class WebService
{
public string dbConStr;
private HttpListener svcHttpListener;
public Action<string, string> LogEvent;
public Action<UploadDataRecords> GetReportEvent;
private void logEvent(string msg, string warn = "正常")
{
LogEvent?.Invoke(warn, msg);
}
private void getReportEvent(UploadDataRecords data)
{
GetReportEvent?.Invoke(data);
}
RecordsService service = new RecordsService();
public void start(string HttpIP, int HttpPort)
{
try
{
if (HttpPort > 0)
{
//logEvent("Web服务启动...");
this.svcHttpListener = new HttpListener();
List<string> lstIp = HttpUtil.getLocalIPList();
//logEvent($"Web服务已启动运行于端口:{Config.LocalHttpPort.ToString()}, 监听Ip:{string.Join("|", lstIp)}");
//if (!string.IsNullOrWhiteSpace(Config.LocalIp) && lstIp.FindIndex(m => m.Contains(Config.LocalIp)) >= 0)//没指定IP/指定的不对
//{
// lstIp.Clear();
// lstIp.Add(Config.LocalIp);
//}
//lstIp.Clear();
if (lstIp.Count < 1)
{
lstIp.Add(HttpIP);
lstIp.Add("127.0.0.1");
}
logEvent($"Web服务已启动运行于端口:{HttpPort.ToString()}, 监听Ip:{string.Join("|", lstIp)}");
//for (int i = 0; i < lstIp.Count; i++)
// this.svcHttpListener.Prefixes.Add("http://" + lstIp[i] + ":" + HttpPort.ToString() + "/");
this.svcHttpListener.Prefixes.Add("http://*:" + HttpPort.ToString() + "/");
//svcHttpListener.Prefixes.Add($"https://+:{HttpPort}");
this.svcHttpListener.Start();
//logEvent($"Web服务已启动运行于端口:{Config.LocalHttpPort.ToString()}, 监听Ip:{string.Join("|", lstIp)}");
//this.svcHttpListener.GetContext().Response.AppendHeader("Access-Control-Allow-Origin", "*");//后台跨域请求,通常设置为配置文件
//this.svcHttpListener.GetContext().Response.AppendHeader("Access-Control-Allow-Credentials", "true"); //后台跨域请求
this.svcHttpListener.BeginGetContext(new AsyncCallback(this.GetContextCallBack), this.svcHttpListener);
}
//------WEB Socket
//if (Config.localIp != "" && Config.localSocketPort > 0)
//{
// logEvent( "WebSocket服务启动...");
// this.wssv = new WebSocketServer(Config.localSocketPort);
// this.wssv.AddWebSocketService<Socket1>("/socket1");
// this.wssv.Start();
// logEvent( "WebSocket服务已启动。");
//}
}
catch (Exception ex)
{
logEvent("Web服务启动失败,ex=" + ex.Message, "错误");
}
}
public void stop()
{
logEvent("正在停止WEB服务...");
try
{
if (this.svcHttpListener != null && this.svcHttpListener.IsListening)
{
this.svcHttpListener.Stop();
this.svcHttpListener.Close();
this.logEvent("Web服务已停止!");
}
//if (this.svcWebSocket != null && this.svcWebSocket.IsListening)
//{
// this.svcWebSocket.Stop();
// this.svcWebSocket = null;
// this.AddTextEvent("WebSocket", "WebSocket服务已停止!");
//}
}
catch (Exception ex)
{
logEvent("Web服务停止失败,ex=" + ex.Message, "错误");
}
}
private void GetContextCallBack(IAsyncResult ar)
{
this.svcHttpListener = (ar.AsyncState as HttpListener);
HttpListenerContext httpListenerContext;
try
{
httpListenerContext = this.svcHttpListener.EndGetContext(ar);
//httpListenerContext.Response.AppendHeader("Access-Control-Allow-Origin", "*");//后台跨域请求,通常设置为配置文件
//httpListenerContext.Response.AppendHeader("Access-Control-Allow-Credentials", "true"); //后台跨域请求
//httpListenerContext.Response.AppendHeader("Access-Control-Allow-Methods", "GET,POST");
httpListenerContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
httpListenerContext.Response.AddHeader("Access-Control-Allow-Headers", "*");
httpListenerContext.Response.AddHeader("Access-Control-Allow-Methods", "*");
this.svcHttpListener.BeginGetContext(new AsyncCallback(this.GetContextCallBack), this.svcHttpListener);
}
catch (Exception ex)
{
logEvent("ex:" + ex.StackTrace, "错误");
return;
}
//
string sessionId = Convert.ToInt32(DateTime.Now.ToString("mmssfff")).ToString();//.ToString("X");
string reqHttpMethod = httpListenerContext.Request.HttpMethod;
string reqUrl = httpListenerContext.Request.RawUrl;
string reqData = "";
try
{
this.logEvent($"{sessionId} / 收到请求:{reqHttpMethod} To Url:{reqUrl}");
reqData = HttpUtil.getPostData(httpListenerContext.Request);
this.logEvent($"{sessionId} / 请求数据:{reqData}");
var subUrls = reqUrl.Trim(new char[] { '/' }).Split(new char[] { '/' });
if (subUrls[0].ToLower() == "static")
{
#region
//string InputStream = ""; //上传的数据
//using (var streamReader = new StreamReader(httpListenerContext.Request.InputStream))
// InputStream = streamReader.ReadToEnd();
// string filePath = Config.appBasePath;
string filePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
foreach (var sub in subUrls)
filePath += "\\" + sub;
if (!File.Exists(filePath)) filePath = filePath + "\\index.html";
if (!File.Exists(filePath))
{
httpListenerContext.Response.ContentLength64 = 0;
httpListenerContext.Response.StatusCode = 404;
httpListenerContext.Response.Abort();
}
else
{
httpListenerContext.Response.StatusCode = 200;
string exeName = Path.GetExtension(filePath);
httpListenerContext.Response.ContentType = HttpUtil.GetContentType(exeName);
FileStream fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite);
int byteLength = (int)fileStream.Length;
byte[] fileBytes = new byte[byteLength];
fileStream.Read(fileBytes, 0, byteLength);
fileStream.Close();
fileStream.Dispose();
httpListenerContext.Response.ContentLength64 = byteLength;
httpListenerContext.Response.OutputStream.Write(fileBytes, 0, byteLength);
//httpListenerContext.Response.OutputStream.Close();
}
#endregion
return;
}
if (reqData == null)
throw new Exception("请求数据不可为空!");
httpListenerContext.Response.StatusCode = 200;
JObject joReqData = JObject.Parse(reqData);
string respText;
JObject result = new JObject();
string sourceSessionId;
switch (subUrls[0].ToLower())
{
case "static": //上面已处理
break;
case "test":
HttpUtil.writeToHttpContext_text(httpListenerContext.Response, "测试回应!");
break;
case "api":
switch (subUrls[1].ToLower())
{
//查询数据
case "query_table":
#region
//if (httpListenerContext.Request.HttpMethod != "POST")
// goto case "http_error";
result = getTableList(joReqData);
respText = JsonConvert.SerializeObject(result);
this.logEvent($"{sessionId} / 返回:{(respText.Length > 30 ? respText.Substring(0, 30) : respText)}");
if (!HttpUtil.writeToHttpContext_json(httpListenerContext.Response, respText))
this.logEvent($"{sessionId} / http返回时连接已断开");
#endregion
break;
//下载数据
case "get_defect_from_batch_reel"://读取缺陷文件名列表和JSON数组
#region
//if (httpListenerContext.Request.HttpMethod != "POST")
// goto case "http_error";
result = getDefectFromBatchReel(joReqData);
respText = JsonConvert.SerializeObject(result);
this.logEvent($"{sessionId} / 返回:{(respText.Length > 30 ? respText.Substring(0, 30) : respText)}");
if (!HttpUtil.writeToHttpContext_json(httpListenerContext.Response, respText))
this.logEvent($"{sessionId} / http返回时连接已断开");
#endregion
break;
default:
HttpUtil.writeToHttpContext_text(httpListenerContext.Response, "未知请求!");
break;
}
break;
case "http_error":
result.Add("code", -1);
result.Add("msg", "不支持的请求协议!");
respText = JsonConvert.SerializeObject(result);
this.logEvent($"{sessionId} / 返回:{respText}");
if (!HttpUtil.writeToHttpContext_json(httpListenerContext.Response, respText))
{
this.logEvent($"{sessionId} / http返回时连接已断开");
//this.logEvent( id + " /http连接已断开" + (string.IsNullOrWhiteSpace(callback_url) ? "无法返回结果!" : "通过回调返回" + callback_url), 1);
//if (callback_url != null && callback_url != "")
// HttpUtil.post(callback_url, respText);
}
break;
case "url_error":
result.Add("code", -2);
result.Add("msg", "URL地址错误");
respText = JsonConvert.SerializeObject(result);
this.logEvent($"{sessionId} / 返回:{respText}");
if (!HttpUtil.writeToHttpContext_json(httpListenerContext.Response, respText))
{
this.logEvent($"{sessionId} / http返回时连接已断开");
//this.logEvent( id + " /http连接已断开" + (string.IsNullOrWhiteSpace(callback_url) ? "无法返回结果!" : "通过回调返回" + callback_url), 1);
//if (callback_url != null && callback_url != "")
// HttpUtil.post(callback_url, respText);
}
break;
case "param_error":
result.Add("code", -3);
result.Add("msg", "参数错误!");
respText = JsonConvert.SerializeObject(result);
this.logEvent($"{sessionId} / 返回:{respText}");
if (!HttpUtil.writeToHttpContext_json(httpListenerContext.Response, respText))
{
this.logEvent($"{sessionId} / http返回时连接已断开");
//this.logEvent( id + " /http连接已断开" + (string.IsNullOrWhiteSpace(callback_url) ? "无法返回结果!" : "通过回调返回" + callback_url), 1);
//if (callback_url != null && callback_url != "")
// HttpUtil.post(callback_url, respText);
}
break;
default:
HttpUtil.writeToHttpContext_text(httpListenerContext.Response, "未知请求!");
break;
}
}
catch (Exception ex)
{
this.logEvent($"{sessionId} / 异常:{ex.Message}\r\n{ex.StackTrace}", "错误");
httpListenerContext.Response.StatusCode = 500;
}
finally
{
try
{
httpListenerContext.Response.OutputStream.Close();//客户端断开时会异常
}
catch { }
}
}
/// <summary>
/// 查询批号卷号数据
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
private JObject getTableList(JObject req)
{
JObject res = new JObject();
try
{
string model, batch = "", reel = "", order = "";
int totalCount = 0;
if (req.ContainsKey("batch")) batch = req.Value<string>("batch");
if (req.ContainsKey("reel")) reel = req.Value<string>("reel");
var db = new SqlSugarClient(new ConnectionConfig()
{
DbType = SqlSugar.DbType.MySql,
//InitKeyType = InitKeyType.Attribute,
IsAutoCloseConnection = true,
ConnectionString = dbConStr
});
List<UploadDataRecords> datalist = db.Queryable<UploadDataRecords>()
.Includes(m => m.DefectInfoList)
.Includes(m => m.QualifiedLimitList)
.Includes(m => m.GradeLimitList)
.ToList();
List<string> list = new List<string>();
var Find = datalist.Where(d => d.BatchId == batch && d.ReelId.IndexOf(reel)>=0).ToList();
if (Find != null && Find.Count > 0)
{
totalCount = Find.Count;
foreach (var d in Find)
{
list.Add($"PH:{d.BatchId},JH:{d.ReelId},FJH:{d.PartReelId}");
}
}
res.Add("code", 200);
res.Add("data", JArray.FromObject(list));
res.Add("totalCount", totalCount);
}
catch (Exception ex)
{
res.Add("code", -9);
res.Add("data", ex.Message);
}
return res;
}
/// <summary>
/// 获取并发送数据
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
private JObject getDefectFromBatchReel(JObject req)
{
int err = 0;
JObject res = new JObject();
try
{
string batch = req.Value<string>("batch");
string reel = req.Value<string>("reel");
var db = new SqlSugarClient(new ConnectionConfig()
{
DbType = SqlSugar.DbType.MySql,
//InitKeyType = InitKeyType.Attribute,
IsAutoCloseConnection = true,
ConnectionString = dbConStr
});
var data = db.Queryable<UploadDataRecords>()
.Includes(m => m.DefectInfoList)
.Includes(m => m.QualifiedLimitList)
.Includes(m => m.GradeLimitList)
.First(m => m.BatchId == batch && m.ReelId == reel);
if(data == null )
throw new Exception($"批号:{batch},卷号:{reel},数据不存在!");
err = 2;
getReportEvent(data);
string file_path = $"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}\\temp.xlsx";
//--缺陷
if (!string.IsNullOrEmpty(file_path))
{
if (!File.Exists(file_path))
throw new Exception(file_path + " 缺陷文件不存在!");
res.Add("code", 200);
//res.Add("data", Convert.ToBase64String(File.ReadAllBytes(file_path)));
res.Add("data", (File.ReadAllBytes(file_path)));
}
else
throw new Exception($"文件错误file_name={file_path}");
}
catch (Exception ex)
{
res.Add("code", -9);
res.Add("data", ex.Message);
}
return res;
}
}
public static class HttpUtil
{
/// <summary>
/// 获取本机IP地址列表
/// </summary>
/// <param name="_type">Wireless80211:本地所有IP仅127.0.0.1Ethernet:仅获取以太网接口的 IP 地址</param>
public static List<string> getLocalIPList(NetworkInterfaceType _type = NetworkInterfaceType.Unknown)
{
List<string> output = new List<string>();
foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
{
if ((_type == NetworkInterfaceType.Unknown || item.NetworkInterfaceType == _type) && item.OperationalStatus == OperationalStatus.Up)
{
foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
{
//API.OutputDebugString($"{item.NetworkInterfaceType.ToString()}; {ip.Address.AddressFamily.ToString()}; {ip.Address.ToString()}");
output.Add(ip.Address.ToString());
}
}
}
}
return output;
}
//读取请求数据
public static string getPostData(HttpListenerRequest request)
{
if (!request.HasEntityBody)
return null;
string result;
using (Stream inputStream = request.InputStream)
{
using (StreamReader streamReader = new StreamReader(inputStream, Encoding.UTF8))
result = streamReader.ReadToEnd();
}
return result;
}
/// <summary>
/// POST请求接口调用
/// </summary>
/// <param name="url"></param>
/// <param name="json"></param>
/// <returns></returns>
public static void post(string url, string json, Action<JObject> callBack = null)
{
System.Threading.ThreadPool.QueueUserWorkItem(
new WaitCallback(o =>
{
var data = (JObject)o;
if (callBack == null)
postSync(data["url"].ToString(), data["json"].ToString(), false);
else
callBack(postSync(data["url"].ToString(), data["json"].ToString()));
}),
JObject.FromObject(new { url, json })
);
}
//HttpWebRequest方式
public static JObject postSync2(string url, string json, bool recvResp = true)
{
JObject resp = new JObject();
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
//request.ContentType = "application/x-www-form-urlencoded";
request.ContentType = "application /json";
StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.UTF8);
requestWriter.Write(json);
requestWriter.Flush();
requestWriter.Close();
if (recvResp)
{
WebResponse webResponse = request.GetResponse();
Stream webStream = webResponse.GetResponseStream();
StreamReader responseReader = new StreamReader(webStream);
resp.Add("data", responseReader.ReadToEnd());
resp.Add("success", true);
}
else
{
request.GetResponse().Close();//必需调用此GetResponse后上面的write才会发送出去
resp.Add("data", "");
resp.Add("success", true);
}
}
catch (Exception ex)
{
resp.Add("success", false);
resp.Add("data", ex.Message);
}
return resp;
}
//HttpClient方式
public static JObject postSync(string url, string json, bool recvResp = true, bool isJson = false)
{
JObject resp = new JObject();
try
{
HttpClient http = new HttpClient();
StringContent dataContent;
//第一种方式data是json格式
if (isJson)
dataContent = new StringContent(json, System.Text.Encoding.UTF8, "application/json"); // {"PageNum":"1","PageSIze":"20","info":"311011500300661"}
else
{
// 第二种方式form表单提交 内容post 提交都在StringContent请求body中添加
string lsUrlEncodeStr = json2Params(JObject.Parse(json));
dataContent = new StringContent(lsUrlEncodeStr, System.Text.Encoding.UTF8, "application/x-www-form-urlencoded"); //PageNum=1&PageSize=20&info=311011500300661
}
http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "token");
var taskstr = http.PostAsync(url, dataContent).Result.Content.ReadAsStringAsync();
//API.OutputDebugString("wlq postSync:url=" + url + ";resp=" + taskstr.Result);
//读取返回数据
//return taskstr.Result;
if (recvResp)
{
resp.Add("data", taskstr.Result);
resp.Add("success", true);
}
else
{
resp.Add("data", "");
resp.Add("success", true);
}
}
catch (Exception ex)
{
resp.Add("success", false);
resp.Add("data", ex.Message);
}
return resp;
}
/// <summary>
/// 向HTTP连接写入数据
/// </summary>
/// <param name="resp">HttpListenerContext.Response</param>
/// <param name="data"></param>
/// <returns>如果连接关闭返回 false</returns>
public static bool writeToHttpContext(HttpListenerResponse resp, byte[] dataBuff)
{
try
{
resp.OutputStream.Write(dataBuff, 0, dataBuff.Length);
resp.OutputStream.Flush();
return true;
}
catch (Exception ex)
{
return false;
}
}
public static bool writeToHttpContext_json(HttpListenerResponse resp, string json)
{
byte[] buff = Encoding.UTF8.GetBytes(json);
resp.ContentType = "application/json";
resp.ContentEncoding = Encoding.UTF8;
return writeToHttpContext(resp, buff);
}
public static bool writeToHttpContext_text(HttpListenerResponse resp, string text)
{
byte[] buff = Encoding.UTF8.GetBytes(text);
resp.ContentType = "application/text";
resp.ContentEncoding = Encoding.UTF8;
return writeToHttpContext(resp, buff);
}
private static string json2Params(JObject json)
{
string result = "";
IEnumerable<JProperty> properties = json.Properties();
foreach (JProperty item in properties)
{
result += item.Name.ToString() + "=" + item.Value.ToString() + "&";
// item.Name 为 键
// item.Value 为 值
}
result = result.Substring(0, result.Length - 1);
//string result1 = WebUtility.UrlEncode(result);//转义字符大写
////string result2 = HttpUtility.UrlEncode(result);//转义字符小写
return result;
}
/// <summary>
/// 获取文件对应MIME类型
/// </summary>
/// <param name="fileExtention">文件扩展名,如.jpg</param>
/// <returns></returns>
public static string GetContentType(string fileExtention)
{
if (string.Compare(fileExtention, ".html", true) == 0 || string.Compare(fileExtention, ".htm", true) == 0)
return "text/html;charset=utf-8";
else if (string.Compare(fileExtention, ".js", true) == 0)
return "application/javascript";
else if (string.Compare(fileExtention, ".css", true) == 0)
return "text/css";
else if (string.Compare(fileExtention, ".png", true) == 0)
return "image/png";
else if (string.Compare(fileExtention, ".jpg", true) == 0 || string.Compare(fileExtention, ".jpeg", true) == 0)
return "image/jpeg";
else if (string.Compare(fileExtention, ".gif", true) == 0)
return "image/gif";
else if (string.Compare(fileExtention, ".swf", true) == 0)
return "application/x-shockwave-flash";
else if (string.Compare(fileExtention, ".bcmap", true) == 0)
return "image/svg+xml";
else if (string.Compare(fileExtention, ".properties", true) == 0)
return "application/octet-stream";
else if (string.Compare(fileExtention, ".map", true) == 0)
return "text/plain";
else if (string.Compare(fileExtention, ".svg", true) == 0)
return "image/svg+xml";
else if (string.Compare(fileExtention, ".pdf", true) == 0)
return "application/pdf";
else if (string.Compare(fileExtention, ".txt", true) == 0)
return "text/*";
else if (string.Compare(fileExtention, ".dat", true) == 0)
return "text/*";
else
return "application/octet-stream";//application/octet-stream
}
}
}