using BLL; using Model; using Newtonsoft.Json.Linq; using Org.BouncyCastle.Asn1.Tsp; using Spire.Pdf; using Spire.Pdf.Utilities; using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.IO; using System.Linq; using System.Net; using System.Text; namespace FineUIPro.Web.HJGL.DataIn { public partial class PipelineGrid : PageBase { public string fileUrl { get { return (string)ViewState["fileUrl"]; } set { ViewState["fileUrl"] = value; } } public string ckbSkipFirst { get { return (string)ViewState["ckbSkipFirst"]; } set { ViewState["ckbSkipFirst"] = value; } } private string IsPDMS { get { return (string)ViewState["IsPDMS"]; } set { ViewState["IsPDMS"] = value; } } public DataSet set { get { return (DataSet)ViewState["set"]; } set { ViewState["set"] = value; } } public DataSet setAfterProcess { get { return (DataSet)ViewState["setAfterProcess"]; } set { ViewState["setAfterProcess"] = value; } } public List isoList { get { return (List)Session["isoList"]; } set { Session["isoList"] = value; } } #region 加载 /// /// 加载页面 /// /// /// protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { fileUrl = Request.Params["fileUrl"]; ckbSkipFirst = Request.Params["ckbSkipFirst"]; set = new DataSet(); setAfterProcess = new DataSet(); isoList = new List(); InitGrid(); } } #endregion /// /// 关闭弹出窗 /// /// /// protected void InitGrid() { // 加载PDF文档 PdfDocument pdf = new PdfDocument(); if (!File.Exists(fileUrl)) { return; } pdf.LoadFromFile(fileUrl); PdfTableExtractor extractor = new PdfTableExtractor(pdf); // 遍历每一页 int i = 0; if (ckbSkipFirst == "1") { i = 1; } var getPipeline = from x in Funs.DB.HJGL_Pipeline where x.ProjectId == this.CurrUser.LoginProjectId select x; var getMedium = from x in Funs.DB.Base_Medium where x.ProjectId == this.CurrUser.LoginProjectId select x;//介质 var getPipeLineClass = from x in Funs.DB.Base_PipingClass where x.ProjectId == this.CurrUser.LoginProjectId select x;//管道等级 var getDetectionRate = from x in Funs.DB.Base_DetectionRate select x;//探伤比例 var getDetectionType = from x in Funs.DB.Base_DetectionType select x;//探伤类型 var getPressurePipingClass = from x in Funs.DB.Base_PressurePipingClass select x;//压力管道级别 var getTestMedium = from x in Funs.DB.Base_TestMedium where x.TestType == "1" select x;//压力试验介质 var getLeakMedium = from x in Funs.DB.Base_TestMedium where x.TestType == "2" select x;//泄露性试验介质 var getPurgeMethod = from x in Funs.DB.Base_PurgeMethod select x; var getMaterial = from x in Funs.DB.Base_Material select x; for (; i < pdf.Pages.Count; i++) { PdfPageBase page = pdf.Pages[i]; // 提取页面中的表格 PdfTable[] tables = extractor.ExtractTable(i); // 输出找到的表格数量 Console.WriteLine($"第 {i + 1} 页找到 {tables.Length} 个表格"); // 遍历提取到的表格 for (int j = 0; j < tables.Length; j++) { PdfTable table = tables[j]; DataTable dtTemp = new DataTable(); for (int col = 0; col < table.GetColumnCount(); col++) { dtTemp.Columns.Add("col" + col); } // 遍历表格的行列 for (int row = 0; row < table.GetRowCount(); row++) { DataRow rowData = dtTemp.NewRow(); dtTemp.Rows.Add(rowData); for (int col = 0; col < table.GetColumnCount(); col++) { string text = table.GetText(row, col); rowData[col] = table.GetText(row, col); Console.Write($"{text}\t"); } Console.WriteLine(); // 换行 } if (dtTemp.Rows.Count > 0 && dtTemp.Columns.Count > 1) {// 2. 转换为CSV string csvContent = ConvertDataTableToCsv(dtTemp); Console.WriteLine("生成的CSV内容:"); Console.WriteLine(csvContent); // 3. 上传到服务器 string uploadUrl = "http://localhost:8000/api/table/clean"; // 替换为实际上传地址 string fileName = $"data_{DateTime.Now:yyyyMMddHHmmss}.csv"; //"管线号", "公称直径", "管道等级", "管道材料", "主要介质", "起止点", "操作参数温度", "操作参数压力", "设计参数温度", "设计参数压力", "隔热工程代号", "隔热材料", "厚度", "介质", "压力", "比例", "方法", "合格等级", "PID尾号", "压力管道类别", "应力分析题号", "备注" try { Grid grid = new Grid(); grid.ShowGridHeader = true; grid.Title = dtTemp.TableName; grid.AllowColumnLocking = true; grid.DataKeyNames = new string[] { "Id" }; foreach (DataColumn dc in dtTemp.Columns) { grid.Columns.Add(new BoundField() { DataField = dc.ColumnName, HeaderText = dc.ColumnName }); } grid.DataSource = dtTemp; grid.DataBind(); Region2.Items.Add(grid); set.Tables.Add(dtTemp); string response = UploadCsvFile(csvContent, uploadUrl, fileName); Grid grid1 = new Grid(); grid1.ShowGridHeader = true; grid1.Title = dtTemp.TableName; grid1.AllowColumnLocking = true; grid1.DataKeyNames = new string[] { "Id" }; JObject dynamicObj = JObject.Parse(response); DataTable dtAfterProcess = new DataTable(); foreach (JToken employeeToken in dynamicObj["headers"]) { dtAfterProcess.Columns.Add(employeeToken.ToString()); grid1.Columns.Add(new BoundField() { DataField = employeeToken.ToString(), HeaderText = employeeToken.ToString() }); } dtAfterProcess.Columns.Add("Id"); foreach (JToken rowData in dynamicObj["rows"]) { // int index = 0; var row = dtAfterProcess.NewRow(); var datas = rowData.ToList(); row["Id"] = Guid.NewGuid().ToString(); foreach(DataRow row1 in dtTemp.Rows) { if (datas[0].ToString() == row1[0].ToString()) { for(int index = 0; index < dtTemp.Columns.Count; index++) { row[index] = row1[index]; } } } //foreach (var d in datas) //{ // row[index] = d.ToString(); index++; //} dtAfterProcess.Rows.Add(row); } grid1.DataSource = dtAfterProcess; grid1.DataBind(); Region1.Items.Add(grid1); setAfterProcess.Tables.Add(dtAfterProcess); string urlHeaderCorrespondence = "http://localhost:8000/api/table/head"; string data = @"{ ""source_headers"": " + dynamicObj["headers"].ToString() + @" , ""target_fields"": [ ""管线号"", ""图纸名称"", ""单线图号"", ""介质名称"", ""管道等级"", ""探伤比例"", ""探伤类型"", ""设计温度"", ""设计压力"", ""压力试验介质"", ""压力试验压力"", ""压力管道级别"", ""管线长度"", ""泄露试验介质"", ""泄露试验压力"", ""吹洗要求"", ""真空试验压力"", ""材质"", ""备注"" ], ""extra_instructions"": ""管线号优先匹配管线代号,优先将含有 Main Fluid 的字段映射到 介质,优先匹配隔热工程代号到绝热类别,压力管道类别映射执行标准,有名称首先匹配名称,没有名称匹配代号,按匹配度从高低输出"" } "; string resHeaderCorrespondence = HeaderCorrespondence(urlHeaderCorrespondence, data, "POST", "application/json;charset=utf-8"); if (!string.IsNullOrEmpty(resHeaderCorrespondence)) { JObject dynamicHeaderCorrespondence = JObject.Parse(resHeaderCorrespondence); Dictionary headerCorrespondenceDic = new Dictionary(); foreach (JToken employeeToken in dynamicHeaderCorrespondence["mapping"]) { headerCorrespondenceDic.Add(employeeToken["source_header"].ToString(), employeeToken["target_field"].ToString()); } foreach (DataRow row in dtAfterProcess.Rows) { HJGL_Pipeline isoInfo = new HJGL_Pipeline(); isoInfo.PipelineId = Guid.NewGuid().ToString(); isoInfo.ProjectId = CurrUser.LoginProjectId; foreach (DataColumn dataColumn in dtAfterProcess.Columns) { if (headerCorrespondenceDic.ContainsKey(dataColumn.ColumnName)) switch (headerCorrespondenceDic[dataColumn.ColumnName]) { case "管线号": isoInfo.PipelineCode = row[dataColumn.ColumnName].ToString(); break; case "单线图号": isoInfo.PipelineCode = row[dataColumn.ColumnName].ToString(); break; case "介质名称": isoInfo.MediumId = getMedium.Where(x => x.MediumName == row[dataColumn.ColumnName].ToString() || x.MediumCode == row[dataColumn.ColumnName].ToString()).Select(x => x.MediumId).FirstOrDefault(); break; case "管道等级": isoInfo.PipingClassId = getPipeLineClass.Where(x => x.PipingClassCode == row[dataColumn.ColumnName].ToString() || x.PipingClassName == row[dataColumn.ColumnName].ToString()).Select(x => x.PipingClassId).FirstOrDefault(); break; case "探伤比例": isoInfo.DetectionRateId = getDetectionRate.Where(x => x.DetectionRateCode == row[dataColumn.ColumnName].ToString() ).Select(x => x.DetectionRateId).FirstOrDefault(); break; case "探伤类型": isoInfo.DetectionType = getDetectionType.Where(x => x.DetectionTypeName == row[dataColumn.ColumnName].ToString() || x.DetectionTypeCode == row[dataColumn.ColumnName].ToString()).Select(x => x.DetectionTypeId).FirstOrDefault(); break; case "设计温度": isoInfo.DesignTemperature = row[dataColumn.ColumnName].ToString() ; break; case "设计压力": isoInfo.DesignPress = row[dataColumn.ColumnName].ToString(); break; case "压力试验介质": isoInfo.TestMedium = getTestMedium.Where(x => x.MediumCode == row[dataColumn.ColumnName].ToString() || x.MediumName == row[dataColumn.ColumnName].ToString()).Select(x => x.TestMediumId).FirstOrDefault(); ; break; case "压力试验压力": isoInfo.TestPressure = row[dataColumn.ColumnName].ToString(); break; case "压力管道级别": isoInfo.PressurePipingClassId = getPressurePipingClass.Where(x => x.PressurePipingClassCode == row[dataColumn.ColumnName].ToString() ).Select(x => x.PressurePipingClassId).FirstOrDefault(); ; break; case "管线长度": isoInfo.PipeLenth = Funs.GetNewDecimal(row[dataColumn.ColumnName].ToString()); break; case "泄露试验介质": isoInfo.LeakMedium = getLeakMedium.Where(x => x.MediumCode == row[dataColumn.ColumnName].ToString() || x.MediumName == row[dataColumn.ColumnName].ToString()).Select(x => x.TestMediumId).FirstOrDefault(); ; break; case "泄露试验压力": isoInfo.LeakPressure = row[dataColumn.ColumnName].ToString() ; break; case "吹洗要求": isoInfo.PCMedium = getPurgeMethod.Where(x => x.PurgeMethodCode == row[dataColumn.ColumnName].ToString()).Select(x => x.PurgeMethodId).FirstOrDefault(); ; break; case "真空试验压力": isoInfo.VacuumPressure = row[dataColumn.ColumnName].ToString(); break; case "材质": isoInfo.MediumId = getMaterial.Where(x => x.MaterialCode == row[dataColumn.ColumnName].ToString()).Select(x => x.MaterialId).FirstOrDefault(); break; case "备注": isoInfo.Remark = row[dataColumn.ColumnName].ToString(); break; } } isoList.Add(isoInfo); } } } catch (Exception e11) { } } Console.WriteLine($"\n--- 表格 {j + 1} ---"); } } this.IsoGrid.DataSource = this.isoList; this.IsoGrid.DataBind(); } /// /// 将DataTable转换为标准CSV格式字符串 /// /// 待转换的DataTable /// CSV格式字符串 public static string ConvertDataTableToCsv(DataTable dt) { if (dt == null || dt.Rows.Count == 0) throw new ArgumentNullException(nameof(dt), "DataTable不能为空或无数据"); StringBuilder csvBuilder = new StringBuilder(); // 1. 写入表头(列名) for (int i = 0; i < dt.Columns.Count; i++) { // 处理表头中的特殊字符 csvBuilder.Append(EscapeCsvValue(dt.Columns[i].ColumnName)); if (i < dt.Columns.Count - 1) csvBuilder.Append(","); } csvBuilder.AppendLine(); // 2. 写入数据行 foreach (DataRow row in dt.Rows) { for (int i = 0; i < dt.Columns.Count; i++) { // 处理单元格中的特殊字符 string cellValue = row[i] == DBNull.Value ? "" : row[i].ToString(); csvBuilder.Append(EscapeCsvValue(cellValue)); if (i < dt.Columns.Count - 1) csvBuilder.Append(","); } csvBuilder.AppendLine(); } return csvBuilder.ToString(); } /// /// 转义CSV中的特殊字符(处理逗号、换行、引号) /// /// 原始值 /// 转义后的值 private static string EscapeCsvValue(string value) { if (string.IsNullOrEmpty(value)) return ""; // 如果包含逗号、换行符、双引号,需要用双引号包裹,并将内部双引号替换为两个双引号 if (value.Contains(",") || value.Contains("\n") || value.Contains("\r") || value.Contains("\"")) { return "\"" + value.Replace("\"", "\"\"") + "\""; } return value; } /// /// 将CSV字符串保存为临时文件并上传到指定服务器 /// /// CSV内容 /// 服务器上传接口地址 /// 上传的文件名 /// 超时时间(毫秒),默认30秒 /// 服务器返回的响应内容 public static string UploadCsvFile(string csvContent, string uploadUrl, string fileName, int timeout = 300000) { string boundary = "----WebKitFormBoundary" + Guid.NewGuid().ToString("N"); using (MemoryStream ms = new MemoryStream()) { void WriteString(string text) { byte[] bytes = Encoding.UTF8.GetBytes(text); ms.Write(bytes, 0, bytes.Length); } // 构建请求体 WriteString($"--{boundary}\r\n"); WriteString($"Content-Disposition: form-data; name=\"file\"; filename=\"{fileName}\"\r\n"); WriteString("Content-Type: text/csv\r\n"); WriteString("\r\n"); WriteString(csvContent); WriteString("\r\n"); WriteString($"--{boundary}\r\n"); WriteString("Content-Disposition: form-data; name=\"extra_instructions\"\r\n"); WriteString("\r\n"); WriteString($"注意数据不要少列\r\n"); WriteString($"--{boundary}--\r\n"); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uploadUrl); request.Method = "POST"; request.ContentType = $"multipart/form-data; boundary={boundary}"; request.ContentLength = ms.Length; request.Accept = "application/json"; request.Timeout = timeout; try { // 发送数据 using (Stream requestStream = request.GetRequestStream()) { ms.Position = 0; ms.CopyTo(requestStream); } // 获取响应 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { string responseText = reader.ReadToEnd(); return responseText; } } catch (WebException ex) { // 处理HTTP错误 if (ex.Response != null) { using (StreamReader reader = new StreamReader(ex.Response.GetResponseStream(), Encoding.UTF8)) { string errorText = reader.ReadToEnd(); throw new Exception($"HTTP错误: {errorText}", ex); } } throw new Exception($"网络错误: {ex.Message}", ex); } } } public static string HeaderCorrespondence(string uploadUrl, string data, string method, string contenttype) { // 5. 创建HTTP请求 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uploadUrl); request.Method = string.IsNullOrEmpty(method) ? "GET" : method; request.ContentType = string.IsNullOrEmpty(contenttype) ? "application/json;charset=utf-8" : contenttype; if (uploadUrl.IndexOf("https") >= 0) { request.ProtocolVersion = HttpVersion.Version10; } if (!string.IsNullOrEmpty(data)) { Stream RequestStream = request.GetRequestStream(); byte[] bytes = Encoding.UTF8.GetBytes(data); RequestStream.Write(bytes, 0, bytes.Length); RequestStream.Close(); } HttpWebResponse response = null; Stream ResponseStream = null; StreamReader StreamReader = null; try { response = (HttpWebResponse)request.GetResponse(); ResponseStream = response.GetResponseStream(); StreamReader = new StreamReader(ResponseStream, Encoding.GetEncoding("utf-8")); string re = StreamReader.ReadToEnd(); StreamReader.Close(); ResponseStream.Close(); return re; } catch (WebException ex) { response = (HttpWebResponse)ex.Response; ResponseStream = response.GetResponseStream(); StreamReader = new StreamReader(ResponseStream, Encoding.GetEncoding("utf-8")); string re = StreamReader.ReadToEnd(); return re; } finally { if (StreamReader != null) { StreamReader.Close(); } if (ResponseStream != null) { ResponseStream.Close(); } if (response != null) { response.Close(); } } } protected void IsoGrid_RowDoubleClick(object sender, GridRowClickEventArgs e) { HJGL_Pipeline iso = null; foreach (var item in isoList) { if (item.PipelineId == IsoGrid.SelectedRowID) { iso = item; break; } } if (PipelineInEdit.dic.ContainsKey(IsoGrid.SelectedRowID)) { PipelineInEdit.dic[IsoGrid.SelectedRowID] = iso; } else { PipelineInEdit.dic.Add(IsoGrid.SelectedRowID, iso); } hdIds.Text = ""; PageContext.RegisterStartupScript(Window1.GetSaveStateReference(hdIds.ClientID) + Window1.GetShowReference(String.Format("PipelineInEdit.aspx?PipelineId={0}", IsoGrid.SelectedRowID, "编辑 - "))); } protected void Window1_Close(object sender, WindowCloseEventArgs e) { if (!string.IsNullOrEmpty(hdIds.Text)) { HJGL_Pipeline iso = null; foreach (var item in isoList) { if (item.PipelineId == hdIds.Text) { iso = item; break; } } for (int i = 0; i < isoList.Count; i++) { isoList[i].PipingClassId = iso.PipingClassId; isoList[i].MediumId = iso.MediumId; isoList[i].DetectionRateId = iso.DetectionRateId; isoList[i].DetectionType = iso.DetectionType; isoList[i].DesignPress = iso.DesignPress; isoList[i].DesignTemperature = iso.DesignTemperature; isoList[i].TestPressure = iso.TestPressure; isoList[i].TestMedium = iso.TestMedium; isoList[i].PipeLenth = iso.PipeLenth; isoList[i].PressurePipingClassId = iso.PressurePipingClassId; isoList[i].LeakPressure = iso.LeakPressure; isoList[i].LeakMedium = iso.LeakMedium; isoList[i].VacuumPressure = iso.VacuumPressure; isoList[i].PCMedium = iso.PCMedium; isoList[i].PCtype = iso.PCtype; isoList[i].Remark = iso.Remark; isoList[i].MaterialId = iso.MaterialId; isoList[i].IsFinished = iso.IsFinished; isoList[i].PlanStartDate = iso.PlanStartDate; isoList[i].PlanEndDate = iso.PlanEndDate; isoList[i].ActStartDate = iso.ActStartDate; isoList[i].ActEndDate = iso.ActEndDate; isoList[i].WBSId = iso.WBSId; isoList[i].State = iso.State; isoList[i].FlowingSection = iso.FlowingSection; isoList[i].UnitId = iso.UnitId; isoList[i].UnitWorkId = iso.UnitWorkId; isoList[i].PipelineCode = iso.PipelineCode; isoList[i].SingleName = iso.SingleName; isoList[i].SingleNumber = iso.SingleNumber; isoList[i].PipingClassId = iso.PipingClassId; } } this.IsoGrid.DataSource = this.isoList; this.IsoGrid.DataBind(); } public static string ConvertUnitWork(object UnitWorkId) { if (UnitWorkId != null) { var unitWork = Funs.DB.WBS_UnitWork.FirstOrDefault(x => x.UnitWorkId == UnitWorkId.ToString()); if (unitWork != null) { return unitWork.UnitWorkName; } } return null; } public static string ConvertUnit(object UnitId) { if (UnitId != null) { var unit = Funs.DB.Base_Unit.FirstOrDefault(x => x.UnitId == UnitId.ToString()); if (unit != null) { return unit.UnitName; } } return null; } public static string ConvertDetectionType(object DetectionTypeId) { if (DetectionTypeId != null) { var steel= Funs.DB.Base_DetectionType.FirstOrDefault(x => x.DetectionTypeId == DetectionTypeId.ToString()); if (steel != null) { return steel.DetectionTypeCode; } } return null; } public static string ConvertDetectionRate(object DetectionRateId) { if (DetectionRateId != null) { var detectionRate = Funs.DB.Base_DetectionRate.FirstOrDefault(x => x.DetectionRateId == DetectionRateId.ToString()); if (detectionRate != null) { return detectionRate.DetectionRateCode; } } return null; } public static string ConvertMedium(object MediumId) { if (MediumId != null) { var materialStandard = Funs.DB.Base_Medium.FirstOrDefault(x => x.MediumId == MediumId.ToString()); if (materialStandard != null) { return materialStandard.MediumCode; } } return null; } public static string ConvertPipingClass(object PipingClassId) { if (PipingClassId != null) { var service = Funs.DB.Base_PipingClass.FirstOrDefault(x => x.PipingClassId == PipingClassId.ToString()); if (service != null) { return service.PipingClassCode; } } return null; } public static string ConvertTestMedium(object TestMediumId) { if (TestMediumId != null) { var isoClass = Funs.DB.Base_TestMedium.FirstOrDefault(x => x.TestMediumId == TestMediumId.ToString()); if (isoClass != null) { return isoClass.MediumName; } } return null; } public static string ConvertPressurePipingClass(object PressurePipingClassId) { if (PressurePipingClassId != null) { var isoClass = Funs.DB.Base_PressurePipingClass.FirstOrDefault(x => x.PressurePipingClassId == PressurePipingClassId.ToString()); if (isoClass != null) { return isoClass.PressurePipingClassCode; } } return null; } public static string ConvertPCMedium(object PurgeMethodId) { if (PurgeMethodId != null) { var isoClass = Funs.DB.Base_PurgeMethod.FirstOrDefault(x => x.PurgeMethodId == PurgeMethodId.ToString()); if (isoClass != null) { return isoClass.PurgeMethodCode; } } return null; } public static string ConvertMaterial(object MaterialId) { if (MaterialId != null) { var isoClass = Funs.DB.Base_Material.FirstOrDefault(x => x.MaterialId == MaterialId.ToString()); if (isoClass != null) { return isoClass.MaterialCode; } } return null; } protected void btnImport_Click(object sender, EventArgs e) { try { if (isoList.Count() > 0) { Funs.DB.HJGL_Pipeline.InsertAllOnSubmit(isoList); Funs.DB.SubmitChanges(); } isoList.Clear(); this.IsoGrid.DataSource = this.isoList; this.IsoGrid.DataBind(); Alert.ShowInTop("导入成功!", MessageBoxIcon.Success); } catch (SqlException ex) { throw; } } } }