using DSWeb.Areas.MvcShipping.DB; using DSWeb.MvcShipping.Comm; using Newtonsoft.Json; using org.apache.pdfbox.cos; using org.apache.pdfbox.pdmodel; using org.apache.pdfbox.pdmodel.common; using org.apache.pdfbox.util; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Runtime.Caching; using System.Text; using System.Web; using System.Web.Mvc; namespace DSWeb.MvcShipping.Controllers { public class OcrController : Controller { private static readonly string ocrFilePath = "ocr_temp_files"; private static readonly string[] allowExts = new string[] { ".pdf", ".xls", ".xlsx", ".doc", ".docx",".rtf" }; //private static readonly int ImageScale = 1; private static readonly int CacheExpire = 5;//缓存到期分钟 [HttpGet] public ActionResult UpOcrAuto(string errMsg) { ViewData["errMsg"] = errMsg; return View(); } [HttpPost] public ActionResult UpOcrFile(float scale = 1.5f) { if (Request.Files.Count > 0) { var ext = Path.GetExtension(Request.Files[0].FileName).ToLower(); if (!allowExts.Contains(ext)) { return RedirectToAction("UpOcrAuto", new { errMsg = "只能上传pdf、excel和word文件!" }); } var ocrDir = Server.MapPath($"~/{ocrFilePath}"); if (!Directory.Exists(ocrDir)) { Directory.CreateDirectory(ocrDir); } var tmpFileName = Guid.NewGuid().ToString(); var saveFilePathName = Path.Combine(ocrDir, tmpFileName + ext); Request.Files[0].SaveAs(saveFilePathName); if (ext == ".xls" || ext == ".xlsx") { Aspose.Cells.Workbook wb = new Aspose.Cells.Workbook(saveFilePathName); string targetPath = Path.Combine(ocrDir, $"{tmpFileName}.pdf"); wb.Save(targetPath, Aspose.Cells.SaveFormat.Pdf); } else if (ext == ".doc" || ext == ".docx" || ext == ".rtf") { Aspose.Words.Document doc = new Aspose.Words.Document(saveFilePathName); string targetPath = Path.Combine(ocrDir, $"{tmpFileName}.pdf"); doc.Save(targetPath, Aspose.Words.SaveFormat.Pdf); } ReadPdf(tmpFileName, scale); #region 挂载到单据管理 var BSNO = Request.Form["BSNO"]; var CUSTID = Guid.NewGuid().ToString(); var path = Server.MapPath("../../UploadFiles/MsOpFiles/" + CUSTID); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } var size = Request.Files[0].ContentLength; var name = Path.GetFileName(Request.Files[0].FileName); var usercode = Convert.ToString(Session["USERCODE"]); var partname = usercode + DateTime.Now.ToString("yyyyMMddHHmmssfff") + name; string filename = path + "\\" + partname; string filenameURL = "../../UploadFiles/MsOpFiles/" + CUSTID + "/" + partname; if (System.IO.File.Exists(filename)) { System.IO.File.Delete(filename); } Request.Files[0].SaveAs(filename); ReceiptContext receiptContext = new ReceiptContext(); Receipt_Doc recDoc = new Receipt_Doc(); recDoc.GID = Guid.NewGuid().ToString(); recDoc.BSNO = BSNO; recDoc.URL = name; recDoc.Driect_URL = filenameURL; recDoc.MODIFIEDUSER = Convert.ToString(Session["USERID"]); recDoc.MODIFIEDTIME = DateTime.Now; recDoc.RECEIPTTYPE = string.Empty; recDoc.documentAttachedCode = string.Empty; recDoc.documentAttachedNo = string.Empty; receiptContext.ReceiptDocs.Add(recDoc); receiptContext.SaveChanges(); #endregion return RedirectToAction("SelectRegion", new { fileName = tmpFileName }); } return RedirectToAction("UpOcrAuto"); } [HttpGet] public ActionResult SelectRegion(string fileName) { ViewData["FileName"] = fileName; return View(); } [HttpPost] public ContentResult GetRegionText(string fileName, int x, int y, int w, int h, float scale = 1.5f) { if (!MemoryCache.Default.Contains(fileName)) { ReadPdf(fileName, scale); } dynamic obj = MemoryCache.Default[fileName]; if (obj != null) { Rectangle rectMouse = new Rectangle(x, y, w, h); List listTextLocations = obj.Result; Size size = obj.Size; StringBuilder sb = new StringBuilder(); int lastY = 0; foreach (var item in listTextLocations) { int xItem = (int)(item.X * scale); int yItem = (int)(size.Height * scale - item.Y * scale); int wItem = (int)(item.Width * scale); int hItem = (int)(item.Height * scale); Rectangle rect = new Rectangle(xItem, yItem, wItem, hItem); if (rect.IntersectsWith(rectMouse)) { if (lastY != 0 && Math.Abs(lastY - item.Y) > 1) { sb.AppendLine(); } sb.Append(item.Text); lastY = (int)item.Y; } } return Content(sb.ToString()); } return Content(""); } [HttpGet] public ActionResult GetCanvasImage(string fileName, float scale = 1.5f) { var ocrDir = Server.MapPath($"~/{ocrFilePath}"); var imgPath = Path.Combine(ocrDir, $"{fileName}_{scale}.jpg"); if (!System.IO.File.Exists(imgPath)) { dynamic obj = MemoryCache.Default[fileName]; if (obj != null) { Size size = obj.Size; DrawImg((int)(size.Width * scale), (int)(size.Height * scale), fileName, scale); } } if (System.IO.File.Exists(imgPath)) { return File(imgPath, "image/jpg"); } return null; } private void ReadPdf(string fileName, float scale) { var ocrDir = Server.MapPath($"~/{ocrFilePath}"); var pdfFileName = System.IO.Path.Combine(ocrDir, fileName + ".pdf"); if (!System.IO.File.Exists(pdfFileName)) { return; } PDDocument document = PDDocument.load(pdfFileName); PrintTextLocations printer = new PrintTextLocations(); java.util.List allPages = document.getDocumentCatalog().getAllPages(); PDPage page = (PDPage)allPages.get(0); PDStream contents = page.getContents(); if (contents != null) { printer.processStream(page, page.findResources(), page.getContents().getStream()); //处理 var listT = new List(); TextSizeLocation t = null; foreach (var item in printer.TextWithLocations) { if (t == null) { t = item.Clone(); listT.Add(t); } else { if (Math.Abs(t.Width + t.X - item.X) <= item.Width / 2 && Math.Abs(t.Height - item.Height) <= 1) //首尾相接 { t.Width += item.Width; t.Text += item.Text; } else { t = item.Clone(); listT.Add(t); } } } var query = from it in listT orderby it.Y descending, it.X select it; listT = query.ToList(); //缓存 MemoryCache.Default.Remove(fileName); var objStore = new { Size = new Size((int)page.findCropBox().getWidth(), (int)page.findCropBox().getHeight()), Result = listT }; MemoryCache.Default.Add(new CacheItem(fileName, objStore), new CacheItemPolicy() { AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddMinutes(CacheExpire)) }); DrawImg((int)(page.findCropBox().getWidth() * scale), (int)(page.findCropBox().getHeight() * scale), fileName, scale); } document.close(); } private void DrawImg(int width, int height, string fileName, float scale) { var ocrDir = Server.MapPath($"~/{ocrFilePath}"); Bitmap bitmap = new Bitmap(width, height); Graphics graphics = Graphics.FromImage(bitmap); graphics.Clear(Color.White); dynamic obj = MemoryCache.Default[fileName]; if (obj != null) { List listTextLocations = obj.Result; Size size = obj.Size; Random rnd = new Random(); foreach (var item in listTextLocations) { float textSize = GetMatchTextSize(item.Width * scale, item.Height * scale, item.Text); graphics.DrawString(item.Text, new Font("黑体", textSize), Brushes.Black, item.X * scale, bitmap.Height - item.Y * scale); } var imgPath = Path.Combine(ocrDir, $"{fileName}_{scale}.jpg"); bitmap.Save(imgPath); } } private float GetMatchTextSize(float width, float height, string str) { float plus = 0.1f; float rtn = 1; Bitmap bm = new Bitmap(1, 1); Graphics g = Graphics.FromImage(bm); for (float i = 1; i < 100; i += plus) { var font = new Font("黑体", i); SizeF size = g.MeasureString(str, font); //if (size.Width > width || size.Height > height) if (size.Width > width) //if (size.Height > height) { if (i > 1) { rtn = i - plus; } break; } } return rtn; } } public class TextSizeLocation { public TextSizeLocation() { } public TextSizeLocation(float x, float y, float width, float height, string text) { this.X = x; this.Y = y; this.Width = width; this.Height = height; this.Text = text; } public float X { get; set; } public float Y { get; set; } public float Width { get; set; } public float Height { get; set; } public string Text { get; set; } public TextSizeLocation Clone() { return new TextSizeLocation() { X = this.X, Y = this.Y, Width = this.Width, Height = this.Height, Text = this.Text }; } } public class PrintTextLocations : PDFTextStripper { public List TextWithLocations { get; set; } public List TextPositions { get; set; } public PrintTextLocations() { this.TextWithLocations = new List(); this.TextPositions = new List(); } public override void processStream(PDPage aPage, PDResources resources, COSStream cosStream) { this.TextWithLocations.Clear(); this.TextPositions.Clear(); base.processStream(aPage, resources, cosStream); } protected override void processTextPosition(TextPosition text) { this.TextPositions.Add(text); this.TextWithLocations.Add(new TextSizeLocation(text.getTextPos().getXPosition(), text.getTextPos().getYPosition(), text.getWidth(), text.getHeight(), text.getCharacter())); } } }