多个PDF文件或PDF数据流的合并

  • 背景
    公司因人员变动和业务整改,提出将原打印(数据库保存的HTML字符串做替换)全部迁移至framework(利用framework完成数据字段替换与EL表达式相似,转换成PDF的二进制流返回),主要是为了方便开发和维护,对应单个的打印文件的预览都没有问题,后期提出新需求,需要勾选多个预览文件时,在一个弹框里面看到所有的pdf文件,就是一个接着一个的长pdf。
    特别说明:所有打印文件的模板(framework文件)全部存在后端。
  • 思路
    1. 对返回的多个PDF流,得到对应的多个二进制数组
    2.将得到的二进制数组组合成一个
    3.将最终得到的二进制数组,outputStream.write(byte[])写回
  • 历程
    1.直接拼接得到的二进制数组可以正确写回,但是只显示第一个完整的PDF文件
       原因:文件流有对应的开始结束标志,如:%%EOF
    2.以为只要删掉除最后一个文件流(二进制数组)中标识“%%EOF”的内容就可以了,然而不只是这几个字,仍然只显示第一个文件的内容
       原因:仔细查看写回的流,发现每一个文件流都有一个很长的头部数据和尾部数据,标志着一个完整的文件(可查看最后的参考流),这里面包含着规则,想要通过删除特定标志字符这种方式拼接PDF文件,不易实现,个人此时也觉得想着这种涉及到底层实现的又比较实用的操作,应该会有工具类来帮助我们实现,通过搜索发现了 PDFMergerUtility
    3.PDFMergerUtility 
    合并多个PDF文件
                OutputStream os = response.getOutputStream(); 
                // apache 提供用于 多个pdf 合并的工具类
                PDFMergerUtility pdfMergerUtility = new PDFMergerUtility();
                for (String param : params) {
                    // 业务返回
                    ByteArrayOutputStream stream = service.export(param1, param);
                    byte[] streamByteArr = stream.toByteArray();
                    ByteArrayInputStream inputStream = new ByteArrayInputStream(streamByteArr);
                    // 添加 pdf 数据源
                    pdfMergerUtility.addSource(inputStream);
                    inputStream.close();
                }
                // 也可以指定要合成的文件和合成后存储的文件位置
                //pdfMergerUtility.setDestinationFileName("F:\\desk\\1company\\result.pdf");
                OutputStream outputStream = new ByteArrayOutputStream();
                // 指定目标文件输出流
                pdfMergerUtility.setDestinationStream(outputStream);
                pdfMergerUtility.mergeDocuments(null);
                // 获取合并后的目标数据流
                ByteArrayOutputStream mergerUtilityDestinationStream = (ByteArrayOutputStream) pdfMergerUtility.getDestinationStream();
                mergerUtilityDestinationStream.writeTo(os);
                outputStream.close();
                os.close();
  • 终章
    PDFMergerUtility
    Apache 提供的一个用于合并多个PDF文件成一个的工具类
    API 参考
    可能是个人流操作用得不是很频繁,所以一开始解决起来有些天真,个人觉得应该还是可以通过一些流操作代码自己实现多个文件的合并,希望在评论区得到各位的指点
  • 写回的流数据参考
    %PDF-1.4
    %����
    4 0 obj
    <</Filter/FlateDecode/Length 6544>>stream  //头部
    M2C<9~;i�}�bė�9��)U��a�I2�$oMr��yR=NN��7'[4����ɔF�(W�|1�S�G����!�s,c�z���}+>&�:��@�]���w�T���#9V����M���Ʊ�Ǜ���$��MT��r>�s����ڽ�t�.xܶS$+���7�����Ӽ�i_�N�|C��w�q�v�cC��4񬩍�~:	
    endstream //尾部
    endobj
    7 0 obj
    <</Descent -140/CapHeight 699/StemV 80/Type/FontDescriptor/FontFile2 6 0 R/Flags 32/FontBBox[0 -140 996 855]/FontName/ABRONC+SimSun/ItalicAngle 0/Ascent 859>>
    endobj
    8 0 obj
    <</DW 1000/Subtype/CIDFontType2/CIDSystemInfo<</Supplement 0/Registry(Adobe)/Ordering(Identity)>>/Type/Font/BaseFont/ABRONC+SimSun/FontDescriptor 7 0 R/W [3[500]8[500]11[500 500]16[500]18[500 500 500 500 500 500 500 500]27[500 500 500]33[500]38[500 500 500 500]44[500]48[500 500]51[500]53[500 500 500]57[500]59[500]79[500 500]22021[500]]/CIDToGIDMap/Identity>>
    endobj
    9 0 obj
    <</Filter/FlateDecode/Length 1223>>stream
    x�]��j�7����L�Jm^d �	�j4��ݴ��>�S��m�����T�ݏ?=\���w��^ۗ�~�ϗ~o��6�u<=_Nڜ�s{߿��R���5�����xy�������������������?��Ow����=_���̟-������x���:�|�c��~)�_��8�a�W���:���X�^�x��6n��4N�j}����O�ҿ�[+%���:��FeH14$R�M��&A�*4]$��)�Z�Q�|�j�(�F$�Z+R��	v�X�S>h�HpEh�!
    W�v;��A[ ��!,:���"��L���eR>��.#��aU>�$�V�N��6$���|�$���$�Z	Hb�M� �]V"����|�7H��AS5���p�t��S#�v�(�
    ��v�(�
    �JtC���țnT��tS�TB�@7%����n��1 �lNp�#H:8�f�\R�y-�t%�j�\R	#&V�8��@2r�"LɈ�I�� Y�¤f�\�J�� ����M�yL��$۵HU0��Q5o.	֧ƕ�S$�j5e���<�a��P��r�@rj�}�7���0�a�m���ۣs�@JʉT��`�t�Zp���R��Y�ڬ$��3�u0y�j"QޤZ�H1o.�A6oRS/m�'��"&��˃�;��l�P\��q��@�ҎKRH������H#o҈R(y�F�#Hs︒��$��!pIX���izL���&�I�f͛�;�|�Q�W
    ���؃�h�>�
    z�v�#�m��D�S���t�z��+��*z0�M��AO�F��� ��p�@�}u�^)�]N$
    ��������]G�\�zh������S$�	g�h��B_=���[����['H�+m�6�H-o.�w4����wtc�
    ���p'���r��+�B?���u�6�NJ�h��0� ��7�S\��L���������� ��w3�/�O��&�:3��
    aH�0�l�6�d��Zn3T
    	^��[�*p3�ʅ`]X�(�ah4֭���`�,9^�c-�!F�@[_xU�Qe�ͨ:vL|����c7[a�h�v$^����Ns�Ɗ.�V��f�Ɖ���x��NV��i�*W�0��U�0�7�:�0b�&L)�^�T"?5��[�fd��+RE����[����Ӻ}�n�Ս�<����~���}������C��
    endstream
    endobj
    3 0 obj
    <</Subtype/Type0/Type/Font/BaseFont/ABRONC+SimSun/Encoding/Identity-H/DescendantFonts[8 0 R]/ToUnicode 9 0 R>>
    endobj
    1 0 obj
    <</Subtype/Form/Filter/FlateDecode/Type/XObject/Matrix [1 0 0 1 0 0]/FormType 1/Resources<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]/Font<</F1 3 0 R>>>>/BBox[0 0 50 50]/Length 39>>stream
    x�s
    ��w3T04RI��``fa`�����r
    ��� Xk�
    endstream
    endobj
    5 0 obj
    <</Kids[2 0 R]/Type/Pages/Count 1/ITXT(2.1.7)>>
    endobj
    10 0 obj
    <</Type/Catalog/Pages 5 0 R>>
    endobj
    11 0 obj
    <</ModDate(D:20200416183526+08'00')/CreationDate(D:20200416183526+08'00')/Producer(iText 2.1.7 by 1T3XT)/Title(��[���[�Thg\\~�)>>
    endobj
    xref
    0 12
    0000000000 65535 f 
    0000046407 00000 n 
    0000006627 00000 n 
    0000046281 00000 n 
    0000000015 00000 n 
    0000046663 00000 n 
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

day day day ...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值