PDF417码的坑

注:我这里的PDF417码主要是用于公文,所以对格式有一定的要求,这也是为什么我这么纠结的原因了,要是没要求那就简单一个码就好了(摊手)

1、 PDF417码的生成与格式要求

先上代码:

public static void createPdf417ForOutDoc(String text, String path) {
        BarcodePDF417 pdf = new BarcodePDF417();
        OutputStream os = null;
        try {
            pdf.setText(text.getBytes(CHARSET));
            byte[]  buff = text.getBytes();
            int textLen = buff.length;
            // 9列数据列最长字节数为504,大于504字节数的字符串不限制长度,不然扫不出来
            if (textLen <= 504) {
                //下面两行很重要,用于定宽 固定中间的列数为10列
                pdf.setOptions(BarcodePDF417.PDF417_FIXED_COLUMNS);
                //设置codeColumns,主要用于指定生成二维码图片的长度
                // 公文二维码的长度一般是189px,所以我的codeColumns=7 
                pdf.setCodeColumns(7);
                //pdf.setYHeight(3F); //设置宽窄比例
            }
            Image pdfImg = pdf.createAwtImage(Color.black, Color.white);
            // 缩放会失真,所以不用
            //Image pdfImgScal = pdfImg.getScaledInstance(189, 46, Image.SCALE_REPLICATE);
            BufferedImage img = new BufferedImage(pdfImg.getWidth(null), 45, BufferedImage.TYPE_INT_RGB);
            Graphics graphics = img.getGraphics();
            graphics.drawImage(pdfImg, 0, 0, img.getWidth(null), img.getHeight(null), Color.white,  null);
            os = new BufferedOutputStream(new FileOutputStream(path));
            ImageIO.write(img, "PNG", os);
        } catch (UnsupportedEncodingException e) {
            ExceptionLogUtil.error(null, e);
        } catch (FileNotFoundException e) {
            ExceptionLogUtil.error(null, e);
        } catch (IOException e) {
            ExceptionLogUtil.error(null, e);
        } finally {
            try {
                if (os != null)
                    os.close();
            } catch (IOException e) {
                ExceptionLogUtil.error(null, e);
            }
        }
    }

1、公文中的条形二维码要求大家可自行上网查询,这里主要介绍我遇到的坑。
这里使用的是开源的插件:iText-2.1.1.jar,其中使用的类是com\lowagie\text\pdf\BarcodePDF417.class
2、由于生成的码会根据内容的多少决定码的长高,这样生成的码显然不适合插入公文,所以我对码的格式进行了控制。通过计算,中间数据列为9列时可容纳最长的字节数为504,如果超过这个限制,虽然可以生成条码,但是扫不出来了,因为码其实会丢失了一部分的数据,毕竟限制了人家长度还要人家给你装这么多东西是不可能的,好在公文的标题常常是有限制的,所以我就在保证大部分码符合要求的前提下结束了这次的折腾。
这里附上完整代码:

package net.evecom.platform.code;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import javax.imageio.ImageIO;
import com.lowagie.text.pdf.BarcodePDF417;
import net.evecom.core.util.ExceptionLogUtil;


/**
 * 生成器_国家标准417条码
 * 
 * @author 
 */
public class BarCodeGenerator {
    /**
     * 字符集
     */
    public final static String CHARSET = "GBK";

    /**
     * <p>
     * 格式:GB0626—2005∧条码编号∧发文单位∧公文种类或刊物名称∧发文字号或期号∧主送单位∧标题∧秘密等级∧紧急程度∧ 公文成文日期或刊物编印日期∧发布层次∧条码制作单位∧条码制作日期∧自定义字段∧|
     * </p>
     * <p>
     * 以∧作为分隔符,以∧|作为结束符
     * </p>
     * <p>
     * 条码版本号:必填,GB0626-2005
     * </p>
     * <p>
     * 条码编号:必填
     * </p>
     * <p>
     * 发文单位:必填
     * </p>
     * <p>
     * 公文种类或刊物名称:选填
     * </p>
     * <p>
     * 发文字号或期号:必填
     * </p>
     * <p>
     * 主送单位:选填
     * </p>
     * <p>
     * 标题:选填
     * </p>
     * <p>
     * 密级:必填
     * </p>
     * <p>
     * 紧急程度:必填
     * </p>
     * <p>
     * 公文成文日期或刊物编印日期:必填
     * </p>
     * <p>
     * 发布层次:选填
     * </p>
     * <p>
     * 条码制作单位:必填
     * </p>
     * <p>
     * 条码制作日期:必填
     * </p>
     * <p>
     * 自定义字段:选填
     * </p>
     */
   
    public static void createPdf417ForOutDoc(String text, String path) {
        BarcodePDF417 pdf = new BarcodePDF417();
        OutputStream os = null;
        try {
            pdf.setText(text.getBytes(CHARSET));
            byte[]  buff = text.getBytes();
            int textLen = buff.length;
            // 9列数据列最长字节数为504,大于504字节数的字符串不限制长度,不然扫不出来
            if (textLen <= 504) {
                //下面两行很重要,用于定宽 固定中间的列数为10列
                pdf.setOptions(BarcodePDF417.PDF417_FIXED_COLUMNS);
                //设置codeColumns,主要用于指定生成二维码图片的长度
                // 公文二维码的长度一般是189px,所以我的codeColumns=7 
                pdf.setCodeColumns(7);
                //pdf.setYHeight(3F); //设置宽窄比例
            }
            Image pdfImg = pdf.createAwtImage(Color.black, Color.white);
            // 缩放会失真,所以不用
            //Image pdfImgScal = pdfImg.getScaledInstance(189, 46, Image.SCALE_REPLICATE);
            BufferedImage img = new BufferedImage(pdfImg.getWidth(null), 45, BufferedImage.TYPE_INT_RGB);
            Graphics graphics = img.getGraphics();
            graphics.drawImage(pdfImg, 0, 0, img.getWidth(null), img.getHeight(null), Color.white,  null);
            os = new BufferedOutputStream(new FileOutputStream(path));
            ImageIO.write(img, "PNG", os);
        } catch (UnsupportedEncodingException e) {
            ExceptionLogUtil.error(null, e);
        } catch (FileNotFoundException e) {
            ExceptionLogUtil.error(null, e);
        } catch (IOException e) {
            ExceptionLogUtil.error(null, e);
        } finally {
            try {
                if (os != null)
                    os.close();
            } catch (IOException e) {
                ExceptionLogUtil.error(null, e);
            }
        }
    }
}

2、 将生成的码插入到偶数页的页脚

获取PDF417码生成的位置及书签的位置

// 往文档中插入机关公文条形二维码
String barCode = AppUtil.getAppAbsolutePath() + outDoc.getBarCodePath();
File file = null;
String filePath = AppUtil.getAppAbsolutePath() + outDoc.getWordFilePath();
file = new File(filePath);
if (file.exists()) {
	try {
		Map<String, String> map = new HashMap<String, String>();
        map.put("barCode", barCode);
        Map<String, String> resultMap = Word2PdfUtil.insertImageToBookmark(filePath, map);
        this.setJsonString("{\"success\":\"" + resultMap.get("success") + "\"," + "\"message\":\"" + resultMap.get("msg") + "\"}");
    } catch (Exception e) {
         logger.error(null, e);
         this.setJsonString("{\"success\":\"false\",\"message\":\"操作失败\"}");
    }
}

往书签中插入图片

package net.evecom.core.util;

import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.aspose.words.DocumentBuilder;
import org.apache.log4j.Logger;
import org.aspectj.weaver.ast.Test;

import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;

/**
 * word转pdf
 * 
 * @author
 *         <p>
 *         支持doc/docx/ooxml/rtf/html/opendocument/pdf/epub/xps/swf相互转化
 *         </p>
 */
public class Word2PdfUtil {
    /**
     * log
     */
    private static Logger logger = Logger.getLogger(Word2PdfUtil.class);

    /**
     * 获取证书
     */
    public static boolean getLicense() {
        boolean result = false;
        try {
            // license.xml放在\WebRoot\WEB-INF\classes路径下
            InputStream is = Test.class.getClassLoader().getResourceAsStream("license.xml");
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            logger.error(null, e);
        }

        return result;
    }

    /**
     * word转pdf,之前pdf已存在则覆盖掉
     */
    public static void doc2pdf(String inPath, String outPath) {
        // 验证license,否则转化的pdf会带水印
        if (!getLicense()) {
            return;
        }
        FileOutputStream os =null;
        try {
            long old = System.currentTimeMillis();

            File file = new File(outPath); // 新建一个空白pdf文档
            os = new FileOutputStream(file);
            Document doc = new Document(inPath); // 加载被转化的word
            doc.acceptAllRevisions();
            doc.save(os, SaveFormat.PDF);

            long now = System.currentTimeMillis();
            logger.info("共耗时:" + ((now - old) / 1000.0) + "秒");// 耗时
        } catch (Exception e) {
            logger.error(null, e);
        } finally {
            try {
                if(os != null){
                    os.close();
                }
            } catch (IOException e) {
                logger.error(null, e);
            }
        }
    }

    /**
     * 对应pdf文件不存在则生成pdf,不强制覆盖
     * @param inPath
     * @param outPath
     */
    public static void doc2pdfWhenNotExist(String inPath, String outPath){
        File file = new File(outPath);
        if(!file.exists()){
            doc2pdf(inPath,outPath);
        }
    }

    /**
     * 往书签中插入图片
     */
    public static Map<String, String> insertImageToBookmark(String filePath, Map<String, String> keyvalues) {
        Map<String, String> resultMap = new HashMap<String, String>();
        resultMap.put("success", "false");
        // 验证license,否则word会带水印
        if (!getLicense()) {
            // 证书授权超时,请联系管理员
            resultMap.put("msg", "操作失败,证书授权超时,请联系管理员");
            return resultMap;
        }
        String bookmark = "";
        String value = "";
        Iterator it = keyvalues.entrySet().iterator();
        try {
            Document doc = new Document(filePath);
            DocumentBuilder builder = new DocumentBuilder(doc);
            //获得文档的页数
            int page = doc.getPageCount();
            if (page % 2 != 0) {
                // 文档页数错误
                resultMap.put("msg", "操作失败,文档末页不是偶数页,条形二维码会与页码重叠,请调整正文");
                return resultMap;
            }
            for (int i = 0; i < keyvalues.size(); i++) {
                Map.Entry entry = (Map.Entry) it.next();
                bookmark = (String) entry.getKey();
                value = String.valueOf(entry.getValue());
                if (builder.moveToBookmark(bookmark)) {
                    builder.insertImage(new FileInputStream(new File(value)));  //插入图片
                    doc.save(filePath);
                    resultMap.put("msg", "操作成功,请在编辑正文中查看");
                } else {
                    // 没有找到书签位置
                    resultMap.put("msg", "操作失败,没有找到书签位置,请确认是否已套红");
                    return resultMap;
                }
            }
        } catch (Exception e) {
            // 文档资源被占用
            resultMap.put("msg", "操作失败,文档资源被占用");
            return resultMap;
        }
        resultMap.put("success", "true");
        return resultMap;
    }
}
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值