zoukankan      html  css  js  c++  java
  • NET|C#生成PDF文件

    项目需要在线生成PDF文件,我首先考虑采用itextsharp控件来实现。具体方法参考 https://sourceforge.net/projects/itextsharp/

    1.首先利用nuget 引入该控件包。
     
    image.png
    2、然后直接创建就可以了。
    using iTextSharp.text;
    using iTextSharp.text.pdf;
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Web;
    
    
    public class CreatePDF
    {
        private static CreatePDF instance;
        public static CreatePDF GetInstance()
        {
            if (instance == null)
            {
                instance = new CreatePDF();
            }
            return instance;
        }
    
        private static Document doc;
        //string fontdb = AppDomain.CurrentDomain.BaseDirectory + "Template\msyh.ttc";
    
        //private static BaseFont bf = BaseFont.CreateFont(@"C://Windows/Fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        static string fontdb = (AppDomain.CurrentDomain.BaseDirectory + "Template\msyh.ttf").Replace("\", "/");
        private static BaseFont bf = BaseFont.CreateFont(fontdb + "", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        //四种字体
        private static Font fontBig = new Font(bf, 14, Font.BOLD);
    
        private static Font fontSmall = new Font(bf, (float)10.5, Font.BOLD);
        private static Font fontSmallNoBold = new Font(bf, (float)10.5);
        private static float IndentationLeft = 50;//距左边距
        //如果要传参数进来,可自定义
        public string GeneratePDF(string name)
        {
            doc = new Document(PageSize.A4);
            string filePath = string.Empty;
            try
            {
                //MemoryStream ms2 = new MemoryStream();
                string fileName = string.Format("{0}.pdf", DateTime.Now.ToString("yyyyMMddHHmmss"));
                filePath = AppDomain.CurrentDomain.BaseDirectory + "Template\" + fileName;
                FileStream fs = new FileStream(filePath, FileMode.Create);//创建临时文件,到时生成好后删除
                PdfWriter writer = PdfWriter.GetInstance(doc, fs);
                writer.CloseStream = false;//把doc内容写入流中
                doc.Open();
    
                //核心操作
                CreateLine(name);//生成一条下横线
    
                #region 添加水印
                string waterMarkName = "机密";
    
                #endregion
    
                doc.Close();
                MemoryStream ms = new MemoryStream();
                if (fs != null)
                {
                    byte[] bytes = new byte[fs.Length];//定义一个长度为fs长度的字节数组
                    fs.Read(bytes, 0, (int)fs.Length);//把fs的内容读到字节数组中
                    ms.Write(bytes, 0, bytes.Length);//把字节内容读到流中
                    fs.Flush();
                    fs.Close();
                }
                MemoryStream waterMS = SetWaterMark(ms, filePath, waterMarkName);//先生成水印,再删除临时文件
                //if (File.Exists(filePath))//判断临时文件是否存在,如果存在则删除
                //{
                //    File.Delete(filePath);
                //    GC.Collect();//回收垃圾
                //}
                //SendFile(fileName, waterMS);//把PDF文件发送回浏览器
            }
            catch (DocumentException ex)
            {
                throw new Exception(ex.Message);
            }
            return filePath;
        }
        #region 生成一条横线
        private static void CreateLine(string name)
        {
            PdfPTable table = new PdfPTable(1);//一个单元格的
    
            PdfPCell cell = new PdfPCell();
            Image gif = Image.GetInstance(AppDomain.CurrentDomain.BaseDirectory + "Template\logo.png");
            gif.ScaleAbsoluteWidth(100);
            cell.AddElement(gif);
            cell.BorderWidth = 0f;
            cell.BorderWidthBottom = 0.2f;
            table.AddCell(cell);
    
            doc.Add(table);
        }
        #endregion
    
    
        #region 生成页码
        private static void AddPageNumberContent()
        {
            var content = new Paragraph("共   页  第   页", fontSmall);
            content.IndentationRight = IndentationLeft + 20;
            content.Alignment = 2;    //居左
            doc.Add(content);
        }
        #endregion
    
        #region 生成单元格
        private static PdfPCell GetPdfCell(string content, Font font, int horizontalAlignment)
        {
    
            Paragraph paragraph = new Paragraph(content, font);
            paragraph.FirstLineIndent = 2;
            paragraph.SetLeading(10, 20);
            paragraph.SpacingAfter = 10;
    
            PdfPCell cell = new PdfPCell(paragraph);
            cell.HorizontalAlignment = horizontalAlignment;//水平位置
            cell.VerticalAlignment = Element.ALIGN_CENTER;//垂直居中
            cell.MinimumHeight = 20;//单元格的最小高度
            cell.Border = 0;
            return cell;
        }
        #endregion
    
        #region 生成水印
        private static MemoryStream SetWaterMark(MemoryStream ms, string filePath, string waterMarkName, string waterMarkAddr = null)
        {
            MemoryStream msWater = new MemoryStream();
            PdfReader pdfReader = null;
            PdfStamper pdfStamper = null;
            try
            {
                pdfReader = new PdfReader(filePath);
                pdfStamper = new PdfStamper(pdfReader, msWater);
    
                int total = pdfReader.NumberOfPages + 1;//获取PDF的总页数
                iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1);//获取第一页
                float width = psize.Width;//PDF页面的宽度,用于计算水印倾斜
                float height = psize.Height;
                PdfContentByte waterContent;
                BaseFont basefont = BaseFont.CreateFont(@"C:WINDOWSFontsSIMFANG.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                PdfGState gs = new PdfGState();
                for (int i = 1; i < total; i++)
                {
                    waterContent = pdfStamper.GetOverContent(i);//在内容上方加水印
                    //透明度
                    waterContent.SetGState(gs);
                    //开始写入文本
                    waterContent.BeginText();
                    waterContent.SetColorFill(BaseColor.RED);
                    waterContent.SetFontAndSize(basefont, 18);
                    waterContent.SetTextMatrix(0, 0);
                    if (waterMarkAddr == null || waterMarkAddr == "")
                    {
                        waterContent.ShowTextAligned(Element.ALIGN_CENTER, waterMarkName, width / 2, height / 2, 55);
                    }
                    else
                    {
                        waterContent.ShowTextAligned(Element.ALIGN_CENTER, waterMarkName, width / 2, height / 2 + 100, 55);
                        waterContent.ShowTextAligned(Element.ALIGN_CENTER, waterMarkAddr, width / 2, height / 2 - 100, 55);
                    }
                    waterContent.EndText();
                }
            }
            catch (Exception)
            {
                return ms;
            }
            finally
            {
                if (pdfStamper != null)
                    pdfStamper.Close();
    
                if (pdfReader != null)
                    pdfReader.Close();
            }
            return msWater;
        }
        #endregion
    
        //-----------------------发送PDF文件回浏览器端----------------------
        public static void SendFile(string fileName, MemoryStream ms, Encoding encoding = null)
        {
            fileName = (fileName + "").Replace(" ", "");
            encoding = encoding ?? Encoding.UTF8;
            if (ms != null && !string.IsNullOrEmpty(fileName))
            {
                System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
                response.Clear();
                response.Charset = encoding.BodyName;// "utf-8";
                if (!HttpContext.Current.Request.UserAgent.Contains("Firefox") && !HttpContext.Current.Request.UserAgent.Contains("Chrome"))
                {
                    fileName = HttpUtility.UrlEncode(fileName, encoding);
                }
                response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
                //为了解决打开,导出NPOI生成的xlsx文件时,提示发现不可读取内容。
                if (!(fileName + "").ToLower().EndsWith(".xlsx"))
                {
                    response.AddHeader("Content-Type", "application/octet-stream");
                    response.BinaryWrite(ms.GetBuffer());
                }
                else
                {
                    response.BinaryWrite(ms.ToArray());
                }
                ms.Close();
                ms = null;
                response.Flush();
                response.End();
            }
        }
    }
    

    特别需要注意一点的是,如果对字体有特殊要求,可以将字库文件放在项目目录下,但字库的文件类型不同,引用时略有差别。

    ttc文件
    BaseFont.CreateFont(@"C://Windows/Fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    
    • 1
    ttf文件
    BaseFont.CreateFont(@"C://Windows/Fonts/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    
    • 1

    这种模式的弊端在于调整文档的格式太痛苦了,你想按照预定的模板生成pdf,格式要按照他的机制一点点写,如果是篇幅比较长的文档,耐心和时间缺一不可。

    在我埋头写了一天之后,同事路过看到我一脸狰狞,细问之,马上丢给我一个包,十分钟后搞定。没有广告,工具类马上贴上来。

    本方法依赖于Aspose.Words,因为版权问题,不要直接用nuget引入,需要去网上down一个破解版。然后将需要生成的文件内容置于一个word中,相应参数用字符标识后,方便替换。最后加入以下工具类直接调用就OK了。

    (破解dll可以在这里自取 链接: https://pan.baidu.com/s/1o7XpCqI 密码: kwpt)

    CrackWord.cs
    using System;
    using System.Reflection;
    
    class CrackWord
    {
        /// <summary>
        /// 16.10.1.0
        /// </summary>
        public static void Crack()//使用前调用一次即可
        {
            string[] stModule = new string[8]
                {
                    "u000Eu2008u200Au2001",
                    "u000Fu2008u200Au2001",
                    "u0002u200Au200Au2001",
                    "u000F",
                    "u0006",
                    "u000E",
                    "u0003",
                    "u0002"
                };
            Assembly assembly = Assembly.GetAssembly(typeof(Aspose.Words.License));
    
            Type typeLic = null, typeIsTrial = null, typeHelper = null;
            foreach (Type type in assembly.GetTypes())
            {
                if ((typeLic == null) && (type.Name == stModule[0]))
                {
                    typeLic = type;
                }
                else if ((typeIsTrial == null) && (type.Name == stModule[1]))
                {
                    typeIsTrial = type;
                }
                else if ((typeHelper == null) && (type.Name == stModule[2]))
                {
                    typeHelper = type;
                }
            }
            if (typeLic == null || typeIsTrial == null || typeHelper == null)
            {
                throw new Exception();
            }
            object lic = Activator.CreateInstance(typeLic);
            int findCount = 0;
    
            foreach (FieldInfo field in typeLic.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
            {
                if (field.FieldType == typeLic && field.Name == stModule[3])
                {
                    field.SetValue(null, lic);
                    ++findCount;
                }
                else if (field.FieldType == typeof(DateTime) && field.Name == stModule[4])
                {
                    field.SetValue(lic, DateTime.MaxValue);
                    ++findCount;
                }
                else if (field.FieldType == typeIsTrial && field.Name == stModule[5])
                {
                    field.SetValue(lic, 1);
                    ++findCount;
                }
    
            }
            foreach (FieldInfo field in typeHelper.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
            {
                if (field.FieldType == typeof(bool) && field.Name == stModule[6])
                {
                    field.SetValue(null, false);
                    ++findCount;
                }
                if (field.FieldType == typeof(int) && field.Name == stModule[7])
                {
                    field.SetValue(null, 128);
                    ++findCount;
                }
            }
            if (findCount < 5)
            {
                throw new NotSupportedException("无效的版本");
            }
        }
    }
    
    ReplaceAndInsertImage.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Aspose.Words;
    using Aspose.Words.Replacing;
    
    public class ReplaceAndInsertImage : IReplacingCallback
    {
        /// <summary>
        /// 需要插入的图片路径
        /// </summary>
        public string Url { get; set; }
    
        public ReplaceAndInsertImage(string url)
        {
            this.Url = url;
        }
    
        public ReplaceAction Replacing(ReplacingArgs e)
        {
            //获取当前节点
            var node = e.MatchNode;
            //获取当前文档
            Document doc = node.Document as Document;
            DocumentBuilder builder = new DocumentBuilder(doc);
            //将光标移动到指定节点
            builder.MoveTo(node);
            //插入图片
            builder.InsertImage(Url);
            return ReplaceAction.Replace;
        }
    }
    
    • Cv.cs 调用生成类
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;
    using Aspose.Words;
    
    public class Cv
    {
        /// <summary>
        /// 生成录用offer文档
        /// </summary>
        /// <param name="source">模板文件</param>
        /// <param name="filespath">生成的PDF目录</param>
        /// <returns></returns>
        public static void Run(string source, string filespath,)
        {
    
            var dic = new Dictionary<string, string>();
           //替换模板文件的参数
            dic.Add("{xingming}","参数");
         
            CrackWord.Crack();
            Aspose.Words.Document doc = new Aspose.Words.Document(source);
    
            foreach (var key in dic.Keys)
            {
    #pragma warning disable 618
                doc.Range.Replace(key, dic[key], false, false);
    #pragma warning restore 618
            }
    
            doc.Save(filespath, SaveFormat.Pdf);
           
        }
    }
    

    source 为模板文件目录,本例中为word 文件。

  • 相关阅读:
    https下 http的会被阻塞 This request has been blocked; the content must be served over HTTPS.
    一文揭秘定时任务调度框架quartz
    JAVA开发者的Golang快速指南
    postman传递对象到spring controller的方式
    Go语言程序结构分析初探
    avalon1.3的新特性预览
    html标签对应的英文原文
    迷你MVVM框架 avalonjs 实现上的几个难点
    firebug,chrome调试工具的使用
    迷你MVVM框架 avalonjs 1.2.4发布
  • 原文地址:https://www.cnblogs.com/Alex80/p/14643245.html
Copyright © 2011-2022 走看看