Pdf文件处理组件对比(Aspose.Pdf,Spire.Pdf,iText7)

目的


 

由于公司是作医疗相关软件的,因此常常和文档打交道,其中就包含了Pdf。医院的Pdf(一般是他们的报告)都千奇百怪,而咱们一直以来都是在用一些免费且可能已经没人维护了的组件来处理Pdf,因此就常常出现Pdf转乱码,甚至直接异常的状况。跟公司管理层反应了好久,终于答应掏腰包采购一款Pdf的处理组件,而且交由我来预研。稍微调查了一下后,最终商业组件选中了 Aspose,Spire还有Leadtool这三家公司的产品,另外因为iTextSharp做为开源的Pdf处理组件太有名,因此我也把它的重写版——iText7加入了对比的列表中,写了一个能够方便执行的Demo项目,想了想,为了那些一样须要Pdf相关资料的同窗,也为了c# 系的开源生态,把这个项目特地整理了一下,发到了Github上,而且写了一些简单的使用说明。git

 

GitHub的地址请戳 这里github

概述


 

本项目主要以常见的五种Pdf处理来进行预研,包括“Pdf转Jpeg”,“Pdf转txt”,“Xps转Pdf”,“将jpeg做为插页插入到Pdf中”,“加水印”。c#

在对上面提出的四种组件进行充分调查后,直接否认了LeadTool,由于文档太少,转化质量也不行,官网下下来的Sample也乱得要死,因此本项目只包含了三个组件的实现 Aspose.Pdf,Spire.Pdf,iText7。测试

这里不得不提的就是iText虽然颇有名,但功能仍是不全的,至少我翻遍了文档也没找到把Pdf转图片和把Xps转Pdf这两个功能,若是有知道的同窗麻烦留言说一声。字体

 

再来看看项目的设计,整个项目功能很简单,都是基于以上五个功能来实现的,因此我定出了这几个功能的接口,而后全部功能组件都基于这个接口能够灵活拓展不一样的处理组件,下面的代码片断是功能接口的定义。网站

    public interface IPdfComponentFunc
    {
        string ComponentName { get; }
        void ToJpeg(string absoluteFilePath, string outputPath);
        void ToTxt(string absoluteFilePath, string outputPath);
        void FromXps(string absoluteFilePath, string outputPath);
        void InsertPage(string absoluteFilePath, string outputPath);
        void AddWaterprint(string absoluteFilePath, string outputPath);
    }

 

功能相信看名字就知道了,而后接下来是三个不一样组件的代码实现。spa

Aspose.Pdf(因为试用版只能转4页,一怒之下搞了个破解版).net

    public class AsposePdfComponent : IPdfComponentFunc
    {
        public string ComponentName => "Aspose.Pdf";

        private const string Key = "PExpY2Vuc2U+DQogIDxEYXRhPg0KICAgIDxMaWNlbnNlZFRvPlNoYW5naGFpIEh1ZHVuIEluZm9ybWF0aW9uIFRlY2hub2xvZ3kgQ28uLCBMdGQ8L0xpY2Vuc2VkVG8+DQogICAgPEVtYWlsVG8+MzE3NzAxODA5QHFxLmNvbTwvRW1haWxUbz4NCiAgICA8TGljZW5zZVR5cGU+RGV2ZWxvcGVyIE9FTTwvTGljZW5zZVR5cGU+DQogICAgPExpY2Vuc2VOb3RlPkxpbWl0ZWQgdG8gMSBkZXZlbG9wZXIsIHVubGltaXRlZCBwaHlzaWNhbCBsb2NhdGlvbnM8L0xpY2Vuc2VOb3RlPg0KICAgIDxPcmRlcklEPjE2MDkwMjAwNDQwMDwvT3JkZXJJRD4NCiAgICA8VXNlcklEPjI2NjE2NjwvVXNlcklEPg0KICAgIDxPRU0+VGhpcyBpcyBhIHJlZGlzdHJpYnV0YWJsZSBsaWNlbnNlPC9PRU0+DQogICAgPFByb2R1Y3RzPg0KICAgICAgPFByb2R1Y3Q+QXNwb3NlLlRvdGFsIGZvciAuTkVUPC9Qcm9kdWN0Pg0KICAgIDwvUHJvZHVjdHM+DQogICAgPEVkaXRpb25UeXBlPkVudGVycHJpc2U8L0VkaXRpb25UeXBlPg0KICAgIDxTZXJpYWxOdW1iZXI+NzM4MDNhYmUtYzZkMi00MTY3LTg2MTgtN2I0NDViNDRmOGY0PC9TZXJpYWxOdW1iZXI+DQogICAgPFN1YnNjcmlwdGlvbkV4cGlyeT4yMDE3MDkwNzwvU3Vic2NyaXB0aW9uRXhwaXJ5Pg0KICAgIDxMaWNlbnNlVmVyc2lvbj4zLjA8L0xpY2Vuc2VWZXJzaW9uPg0KICAgIDxMaWNlbnNlSW5zdHJ1Y3Rpb25zPmh0dHA6Ly93d3cuYXNwb3NlLmNvbS9jb3Jwb3JhdGUvcHVyY2hhc2UvbGljZW5zZS1pbnN0cnVjdGlvbnMuYXNweDwvTGljZW5zZUluc3RydWN0aW9ucz4NCiAgPC9EYXRhPg0KICA8U2lnbmF0dXJlPm5LNVVUR3dZMWVJSEtIV0d2NW5sQUxXUy81bDEzWkFuamlvdnlBcGNqQis0ZjNGbm5yOWhjeUlzazlvVzQySWp0ZFYra2JHZlNSMUV4OUozSGlkaThCeE43aHFiR1BERXNaWGo2RlYxaGl1N2MxWmUyNEp3VGc2UnpsNUNJRHY1YVhxbDQyczBkSGw4eXpreDRBM2RTTU5KTzRiQ094a2V2OFBiOWxSaUc3ST08L1NpZ25hdHVyZT4NCjwvTGljZW5zZT4=";
        private static Stream LStream = (Stream)new MemoryStream(Convert.FromBase64String(Key));
        public AsposePdfComponent()
        {
            SetPdfLicense();
        }

        public void SetPdfLicense()
        {
            var l = new Aspose.Pdf.License();
            //l.SetLicense(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Aspose.Total.lic"));
            l.SetLicense(LStream);
        }


        public void AddWaterprint(string absoluteFilePath, string outputPath)
        {
            var watermarkImgPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DefaultResource", "waterMarkImg.jpeg");
            using (var pdfDocument = new Document(absoluteFilePath))
            using (BackgroundArtifact background = new BackgroundArtifact())
            {
                foreach (Page aPdfPage in pdfDocument.Pages)
                {
                    ImageStamp imageStamp = new ImageStamp(watermarkImgPath);
                    imageStamp.XIndent = 300;
                    imageStamp.YIndent = aPdfPage.PageInfo.Height - 200;
                    imageStamp.Height = 81;
                    imageStamp.Width = 80;
                    aPdfPage.AddStamp(imageStamp);
                }


                pdfDocument.Save(outputPath);
            }
        }

        public void FromXps(string absoluteFilePath, string outputPath)
        {
            // Instantiate LoadOption object using XPS load option
            Aspose.Pdf.LoadOptions options = new XpsLoadOptions();

            // Create document object 
            Aspose.Pdf.Document document = new Aspose.Pdf.Document(absoluteFilePath, options);

            // Save the resultant PDF document
            document.Save(outputPath);
        }

        public void InsertPage(string absoluteFilePath, string outputPath)
        {
            var insertPageImgPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DefaultResource","insertPage.jpeg");
            using (var pdfDocument = new Document(absoluteFilePath))
            using (BackgroundArtifact background = new BackgroundArtifact())
            {
                // Add a new page to document object
                Page page = pdfDocument.Pages.Insert(2);
                page.AddImage(insertPageImgPath, page.Rect);

                pdfDocument.Save(outputPath);
            }
        }

        public void ToJpeg(string absoluteFilePath, string outputPath)
        {
            using (var pdfDocument = new Document(absoluteFilePath))
            {
                for(var i = 1; i < pdfDocument.Pages.Count + 1; i++)
                {

                    using (FileStream imageStream = new FileStream(Path.Combine(outputPath, i.ToString() + ".jpeg"), FileMode.Create))
                    {
                        //Quality [0-100], 100 is Maximum
                        //create Resolution object
                        Resolution resolution = new Resolution(300);
                        JpegDevice jpegDevice = new JpegDevice(resolution, 100);

                        //convert a particular page and save the image to stream
                        jpegDevice.Process(pdfDocument.Pages[i], imageStream);

                        //close stream
                        imageStream.Close();
                    }
                }
            }
        }

        public void ToTxt(string absoluteFilePath, string outputPath)
        {
            var txtAbsorber = new TextAbsorber();
            using (var pdfDocument = new Document(absoluteFilePath))
            {
                pdfDocument.Pages.Accept(txtAbsorber);
                File.WriteAllText(outputPath, txtAbsorber.Text);
            }
        }
    }

 

不想代码篇幅太长,因此另外两个组件的代码实现不贴了。设计

当你每实现一个接口,程序都会自动把它添加到组件(UseComponent)的下拉列表中,以下图所示。3d

 

 

 

由于考虑如今开源生态国际化,因此都写的英文,本人比较懒,也就没作多语言。

Demo使用方法Github上都有写明,这里只贴一下运行后的界面图

使用组件:Aspose,执行次数:10,耗时:27473 毫秒

 

 

 

 结尾语


 

简单地说下我这边的一个预研结果,我这里测试了一堆之前有问题的Pdf,最终发现:

Aspose.Pdf:1,从Xps转到Pdf的功能存在某些缺陷问题,有些Xps文档直接抛了异常。2,转Pdf到Image的功能对系统字体库有依赖,若是缺乏Pdf文件的字体,转出来都是乱码。已经联系他们的技术团队看是否能改善 这两个问题,我就会选用它,目前在我这边印象最好。

Spire.Pdf:1,Pdf转Image的速度要比Aspose快,不过遗憾的是,带有图片的Pdf转Image直接抛了异常。2,转Txt的格式比起Aspose要差不少,但内容没什么毛病。

iText7:1,跟Spire同样,带图片的Pdf处理起来直接抛异常,并且iText没有Xps转Pdf和转Jpeg功能(我翻遍了文档没发现)

 

值得一提的是,速度最快的是iText7,虽然它功能不全,其次是Spire,不过Aspose转出来的东西不多会出问题,Txt的格式基本还原Pdf的原格式,反观Spire和iText这点就很很差,所有密密麻麻排一块去了。

 

这里只实现了我以为比较好的三个组件来对比,若是有同窗有其余更好的组件麻烦推荐下,我能够添加到组件中去,你也能够直接到Github上去Fork这份代码而后拓展本身的组件进行研究。

最近把本身网站重构成了.net core2.0,真的感受到微软的良苦用心,微软都这么推行开源了,做为从c#出身,如今却在带Web组的人只但愿C#系的开源生态能愈来愈好,否则我就要投奔NodeJs了(笑)。

相关文章
相关标签/搜索