基于iTextSharp的PDF文档操作
公司是跨境电商,需要和各种物流打交道,需要把东西交给物流,让他们发到世界各地。其中需要物流公司提供一个运单号,来追踪货物到达哪里?!
最近在和DHL物流公司(应该是个大公司)对接,取运单号的方式是调用对方提供的API,简单说,就是我们传一些发货地址和客户信息,要发的货物等,对方返回一个运单号和物流面单(就是我们淘宝快递上的面单)。过程呢,还是比较顺利的,经过一系列沟通,最终还是实现了功能
下面还是说说没有实现的功能,如果都实现了,也不用写这篇博客了。不足之处在于DHL提供的面单,没有提供要拣哪些货的面单。本来一个完整的面单,包括2部分:物流公司需要贴在包裹上的面单(物流面单)和我们自己发货部门要发哪些东西的面单(拣货面单),两部分组合在一起,发货部门才能正常的完成这个包裹的发货
好吧,终于要引入正题了,DHL公司将物流面单以pdf文件流的形式返回,就是我们可以保存成Pdf文件,这样就容易处理的多,我们自己的拣货面单,如果也可以保存至Pdf文件,这样就可以将这2个Pdf文件一块打印出来,这算是一个折中的解决方案。
-----------------------------------------------------------------------------
博客搬家啦,新地址:
-----------------------------------------------------------------------------
首先,要将拣货数据(含图片)保存至Pdf文档。技术点如下
1, 将DataTable导出至Pdf
2, DataTable中包含图片,也要能导出
3, Pdf类库,字体的引入(居然需要引用字体的绝对路径,想不通)
下面分别讲解
1, 这点就是直接创建iTextSharp中的PdfDataTable对象,直接映射即可。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | private static pdfText.pdf.PdfPTable CreatePdfPTableToPickupLabel(List<TradeDetailModel> listDetail, iTextSharp.text.Font font) { pdfText.pdf.PdfPTable pdtTable = new pdfText.pdf.PdfPTable(5); <strong>pdtTable.WidthPercentage = 95; //占宽度百分比:95%(这句很关键,作用是撑满整个面单)</strong> int [] colWidth = { 2, 4, 2, 2, 2 }; //设置列宽比例 pdtTable.SetWidths(colWidth); //此处,先插入首行,即标题 pdtTable.AddCell( new iTextSharp.text.Phrase( "图片" , font)); pdtTable.AddCell( new iTextSharp.text.Phrase( "基本信息" , font)); pdtTable.AddCell( new iTextSharp.text.Phrase( "单价" , font)); pdtTable.AddCell( new iTextSharp.text.Phrase( "数量" , font)); pdtTable.AddCell( new iTextSharp.text.Phrase( "备注" , font)); //再插入真实拣货数据 int rowCount = listDetail.Count; for ( int i = 0; i < rowCount; i++) { TradeDetailModel modelDetail = listDetail[i]; iTextSharp.text.Image image = PdfUtil.CreatePdfImage(modelDetail.ProductImageBytes); pdtTable.AddCell(image); pdtTable.AddCell( new iTextSharp.text.Phrase(modelDetail.ProductBase, font)); pdtTable.AddCell( new iTextSharp.text.Phrase(modelDetail.Price.ToString() + Environment.NewLine + modelDetail.ProductID, font)); pdtTable.AddCell( new iTextSharp.text.Phrase(modelDetail.Number.ToString() + Environment.NewLine + modelDetail.ProductSpec, font)); pdtTable.AddCell( new iTextSharp.text.Phrase(modelDetail.Remark, font)); } return pdtTable; } |
2, 这点要先生成iTextSharp中Image对象才可以,然后再随生成PdfDataTable中,将Image对象插入单元格(注意:图片尺寸需要定义好)。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /// <summary> /// 创建Pdf所需图像 /// </summary> /// <param name="imageBytes"></param> /// <param name="widthS"></param> /// <param name="heightS"></param> /// <returns></returns> private static iTextSharp.text.Image CreatePdfImage( byte [] imageBytes, float widthS = 60f, float heightS = 60f) { iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(imageBytes); //图片大小要求统一80x80,需根据实际图片 float perW = ( float )Math.Round(widthS / image.Width, 2); float perH = ( float )Math.Round(heightS / image.Height, 2); image.ScalePercent(perW * 100, perH * 100); //设置Dpi值,能够清晰些 image.SetDpi(124, 124); return image; } |
3, 创建字体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /// <summary> /// 创建Pdf所需字体 /// </summary> /// <returns></returns> public static iTextSharp.text.Font CreatePdfFont( float fontSize = 16F) { //黑体 string fontPath = @"C:\Windows\Fonts\simhei.ttf" ; iTextSharp.text.pdf.BaseFont baseFont = iTextSharp.text.pdf.BaseFont.CreateFont(fontPath, iTextSharp.text.pdf.BaseFont.IDENTITY_H, iTextSharp.text.pdf.BaseFont.NOT_EMBEDDED); iTextSharp.text.Font font = new iTextSharp.text.Font(baseFont, fontSize); return font; } |
下面是调用的代码,仅供参考。注:返回的Pdf文件的绝对路径,用于后续打印
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | /// <summary> /// 生成拣货标签pdf文件 /// </summary> /// <param name="modelTrade"></param> /// <param name="dhlLabelFolderName"></param> /// <returns></returns> public static string CreatePickupLabel(TradeModel modelTrade, string dhlLabelFolderName) { //参考地址 //https://www.cnblogs.com/yangy1989/p/5300304.html //http://blog.csdn.net/lideyuans/article/details/51536676 (设置图片百分比) //组装,待生成的pdf文件完整路径 string logisticsNo = modelTrade.R; string pdfFileName = dhlLabelFolderName + logisticsNo + "_Label.pdf" ; FileStream fs = new FileStream(pdfFileName, FileMode.Create); pdfText.Rectangle rect = new pdfText.Rectangle(0f, 0f, 1000f, 1000f); pdfText.Document document = new pdfText.Document(rect, 5f, 5f, 5f, 5f); //创建字体 iTextSharp.text.Font font = PdfUtil.CreatePdfFont(34F); pdfText.pdf.PdfWriter pdfWriter = pdfText.pdf.PdfWriter.GetInstance(document, fs); document.Open(); //增加拣货单品列表 pdfText.pdf.PdfPTable pdfpTable = PdfUtil.CreatePdfPTableToPickupLabel(modelTrade.Details, font); document.Add(pdfpTable); //增加品名备注 pdfText.Paragraph pgraph1 = new pdfText.Paragraph(modelTrade.ItemsDescription, font); document.Add(pgraph1); //增加:发货期限 font.Color = pdfText.BaseColor.RED; pdfText.Paragraph pgraph2 = new pdfText.Paragraph(modelTrade.ShipLimitTimeText, font); document.Add(pgraph2); document.Close(); fs.Close(); return pdfFileName; } |
再将这2个文件,通过C#代码连续打印出来。支持连续打印多个Pdf文件
1 2 3 4 5 6 7 8 9 10 11 12 | //直接调用cmd命令,实现直接打印 foreach ( string printFile in listPrintFile) { Process proc = new Process(); proc.StartInfo.CreateNoWindow = false ; proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; proc.StartInfo.UseShellExecute = true ; proc.StartInfo.FileName = printFile; proc.StartInfo.Verb = "print" ; proc.Start(); proc.Close(); } |
好了,最后的最后,看看效果图吧。前2联是DHL返回的Pdf文件,第3联是我本地生成的Pdf文件,合并成一个完整的发货面单
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库