Java使用itext生成pdf标签的操作方法

 更新时间:2024年12月15日 11:04:48   作者:Java小王子呀  
iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库,通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件,本文给大家介绍了Java使用itext生成pdf标签的操作方法,需要的朋友可以参考下

一、利用Adobe Acrobat DC软件创建pdf模板

备好Adobe Acrobat DC软件

1.excel/jpg/png文件转pdf文件

文件是正常的excel表格填上不会变动的内容

右击打开我们要转换的文件

2.然后点击添加域

3.可以看到域的名字

域的名字是和代码里参数名是一致的

4.调整字体大小/对齐方式等

调整字体格式和大小,对其方式可靠上/居中/靠下

5.保存

ctrl + S 保存后放入项目模板路径下

比如 resources - template 目录下

二,代码部分

首先

1.上依赖

            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itextpdf</artifactId>
                <version>${com.itextpdf.version}</version>
            </dependency>
 
<com.itextpdf.version>5.5.13.2</com.itextpdf.version>

2.Controller层

HttpServletResponse:用于将生成的 PDF 文件直接写入 HTTP 响应流中,以便客户端可以下载或查看 PDF 文件。

    @PostMapping(value = "printlabel/pallet", produces = MediaType.APPLICATION_PDF_VALUE)
    @ApiOperation(value = "打印托盘码", produces = MediaType.APPLICATION_PDF_VALUE)
    public void printlabelPallet(@Valid @RequestBody PalletPrintRequest request, HttpServletResponse response) throws Exception {
        labelService.printlabelPallet(request, response);
    }

目前,方法声明抛出了 Exception,这会导致所有未捕获的异常都被抛出到客户端。为了提高代码的健壮性,建议捕获特定的异常,并根据不同的异常类型返回适当的 HTTP 状态码和错误信息。

例如,你可以使用 @ExceptionHandler 来捕获常见的异常,如 IOExceptionDocumentException 等,并返回 500 Internal Server Error 或其他适当的响应。

3.Service层

按照业务逻辑从数据库获取数据并处理数据,放到合适的对象里

(这里主要是和业务相关,不必深究里面内容,最后能得出需要的数据传出即可)

@Override
    @Lock4j
    @Transactional(rollbackFor = Exception.class)
    public void printlabelPallet(PalletPrintRequest request, HttpServletResponse response) throws Exception {
        Crossdock crossdock = new Crossdock();
        CrossdockPlanConsignee consignee = new CrossdockPlanConsignee();
        CrossdockPlan plan = new CrossdockPlan();
        //暂存
        if (request.getIsTemp()){
            crossdock = crossdockService.getByFieldValue(request.getOrderNo(), Crossdock::getOrderNo);
        }else{
            plan = planService.getByFieldValue(request.getPlanNo(),CrossdockPlan::getPlanNo);
            if (ObjectUtils.isEmpty(plan)){
                throw new ApiException(ResultCode.PARAMES_INVALID,"plan not found");
            }
            crossdock = crossdockService.getValidById(plan.getOrderId());
            consignee = planConsigneeService.getByFieldValue(plan.getId(), CrossdockPlanConsignee::getPlanId);
        }
        Customer customer = customerService.getValidById(crossdock.getCustomerId());
        //托盘标号
        String consigneeName = consignee.getName() != null ? consignee.getName() : "";
        if (request.getIsCustomize() && StringUtils.isNotBlank(request.getPalletNo())){
            consigneeName = request.getPalletNo();
        }else if (request.getIsTemp()) {
            consigneeName += crossdock.getOrderNo();
            consigneeName += LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
            String redisKey = redisService.genKey(new String[]{NoRules.class.getSimpleName()}, consigneeName);
            redisService.setIfAbsent(redisKey, 0, NoRulesEnums.DateFormat.yyMMdd.getDays(), TimeUnit.DAYS);
            Long no = redisService.increment(redisKey);
            consigneeName = consigneeName + String.format("%0" + 5 + "d", no);
        }else {
            consigneeName += LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
            String redisKey = redisService.genKey(new String[]{NoRules.class.getSimpleName()}, consigneeName);
            redisService.setIfAbsent(redisKey, 0, NoRulesEnums.DateFormat.yyMMdd.getDays(), TimeUnit.DAYS);
            Long no = redisService.increment(redisKey);
            consigneeName = consigneeName + String.format("%0" + 5 + "d", no);
        }
        //托盘信息
        List<CrossdockPalletLabelNew> labelList = Lists.newArrayList();
        CrossdockPalletLabelNew palletLabel = new CrossdockPalletLabelNew().setCustomer(customer.getCode())
                .setPrintDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")))
                .setContainerNo(StringUtils.right(crossdock.getContainerNo(), 5))//取后5位
                .setTotalAmount(crossdock.getTotalAmount().stripTrailingZeros().toPlainString())// 转运单总箱数
                .setWarehouse(consignee.getName())// 收件人名称
                .setPieces(request.getPieces().stripTrailingZeros().toPlainString())
                .setBarcode(consigneeName)
                .setPalletNO(consigneeName);
        labelList.add(palletLabel);
        //保存crossdock_plan_pallet
        BigDecimal palletCount = planPalletService.countByFieldValue(consigneeName, CrossdockPlanPallet::getPalletNo);
        if (palletCount.compareTo(BigDecimal.ZERO) <= 0) {
            CrossdockPlanPallet pallet = new CrossdockPlanPallet();
            pallet.setPalletNo(consigneeName).setOrderId(crossdock.getId()).setAmount(request.getPieces());
            if (ObjectUtils.isNotEmpty(plan) && StringUtils.isNotBlank(plan.getId())){
                pallet.setPlanId(plan.getId());
            }
            planPalletService.save(pallet);
        }else {
            throw new ApiException(ResultCode.FORBIDDEN,"msg:the_pallet_code_already_exists");
        }
        //保存crossdock_plan_pda
        BigDecimal pdaCount = planPdaService.countByFieldValue(consigneeName, CrossdockPlanPda::getPalletNo);
        if (pdaCount.compareTo(BigDecimal.ZERO) <= 0) {
            CrossdockPlanPda pda = new CrossdockPlanPda();
            pda.setPalletNo(consigneeName).setOrderNo(crossdock.getOrderNo()).setStatus(CrossdockEnums.PlanPdaStatus.INBOUND.name());
            if (ObjectUtils.isNotEmpty(plan) && StringUtils.isNotBlank(plan.getPlanNo())){
                pda.setPlanNo(plan.getPlanNo());
            }
            if(request.getIsTemp()){
                pda.setSourcePalletNo(PrintEnums.sourcePalletNo.STORAGE.name());
            }else {
                pda.setSourcePalletNo(PrintEnums.sourcePalletNo.PLAN.name());
            }
            planPdaService.save(pda);
        }else {
            throw new ApiException(ResultCode.FORBIDDEN,"msg:the_pallet_code_already_exists");
        }
        //保存托盘打印日志
        PalletPrintLogCreateRequest log = new PalletPrintLogCreateRequest().setOrderId(crossdock.getId())
                .setPalletNo(consigneeName)
                .setIsCustomize(request.getIsCustomize())
                .setPieces(request.getPieces());
        if (ObjectUtils.isNotEmpty(plan) && StringUtils.isNotBlank(plan.getId())){
            log.setPlanId(plan.getId());
        }
        palletPrintLogService.createPalletPrintLog(log);
        printPalletLabel(labelList, response.getOutputStream());
    }

这个是单个的,可以多个,循环把数据放进list即可

这里参数可以放进list里,进行批量生成并拼接到一个pdf里 

private final String TEMPLATE_FONT = "template/font/Alibaba-PuHuiTi-Medium.ttf";
private final String PALLET_TEMPLATE = "template/pallet.pdf";
private final int NUM_TO_PRINT = 2;
 
public void printPalletLabel(List<CrossdockPalletLabelNew> labelList, OutputStream outputStream) throws Exception {
    Document doc = new Document();
    PdfCopy copy = new PdfCopy(doc, outputStream);
    doc.open();
    
    // 创建字体
    BaseFont bf = BaseFont.createFont(TEMPLATE_FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
    
    // 遍历标签列表
    for (CrossdockPalletLabelNew label : labelList) {
        // 每个标签打印 NUM_TO_PRINT 次
        for (int i = 0; i < NUM_TO_PRINT; i++) {
            // 创建字节数组输出流
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            
            // 使用 PdfStamper 打开 PDF 模板
            PdfStamper stamper = new PdfStamper(new PdfReader(PALLET_TEMPLATE), bos);
            
            // 将标签对象转换为 Map
            Map<String, Object> fieldMap = BeanMap.create(label);
            
            // 获取 PDF 模板中的表单字段
            AcroFields fields = stamper.getAcroFields();
            
            // 添加自定义字体
            fields.addSubstitutionFont(bf);
            
            // 遍历表单字段并填充内容
            for (String key : fieldMap.keySet()) {
                if (key.equals(BARCODE)) {
                    // 如果是条形码字段,调用 createBarcode 方法生成条形码
                    createBarcode(stamper.getOverContent(1), label.getBarcode(), fields.getFieldPositions(BARCODE).get(0).position);
                } else {
                    // 否则,设置表单字段的值
                    fields.setField(key, Objects.toString(fieldMap.get(key), StringPool.EMPTY));
                }
            }
            
            // 平坦化表单,防止用户编辑
            stamper.setFormFlattening(true);
            
            // 关闭 PdfStamper
            stamper.close();
            
            // 将生成的页面添加到最终的 PDF 文档中
            copy.addPage(copy.getImportedPage(new PdfReader(bos.toByteArray()), 1));
        }
    }
    
    // 关闭文档
    doc.close();
}

循环两次是业务需要,同一张打印两次

字体可网上自行下载,或者更换其他字体

4.生成条形码

这里可以设置具体的条形码宽度/高度等,(条形码下面默认带条形码扫出来的内容)

    private void createBarcode(PdfContentByte cb, String barcode, Rectangle position) throws DocumentException {
        Barcode128 barcode128 = new Barcode128();
        barcode128.setCode(barcode);
        barcode128.setX(1.7F);
        barcode128.setBarHeight(position.getHeight());
        Image image128 = barcode128.createImageWithBarcode(cb, null, null);
        image128.scaleToFit(position.getWidth(), position.getHeight());
        image128.setAbsolutePosition(position.getLeft() + (position.getWidth() - image128.getScaledWidth()) / 2,
                position.getBottom() + (position.getHeight() - image128.getScaledHeight()) / 2);
        cb.addImage(image128);
    }

三,标签效果图

以上就是Java使用itext生成pdf标签的操作方法的详细内容,更多关于Java itext生成pdf标签的资料请关注脚本之家其它相关文章!

相关文章

  • LinkedHashMap如何保证有序问题

    LinkedHashMap如何保证有序问题

    这篇文章主要介绍了LinkedHashMap如何保证有序问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Spring boot实现热部署的两种方式详解

    Spring boot实现热部署的两种方式详解

    这篇文章主要介绍了Spring boot实现热部署的两种方式,这两种方法分别是使用 Spring Loaded和使用spring-boot-devtools进行热部署,文中给出了详细示例代码和介绍,需要的朋友可以参考学习,下面来一起看看吧。
    2017-04-04
  • spring中@Autowired自动注入依赖项的使用

    spring中@Autowired自动注入依赖项的使用

    当使用@Autowired注解时,它可以自动注入依赖项,例如其他类的实例,本文就来详细的介绍一下,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • java背包问题动态规划算法分析

    java背包问题动态规划算法分析

    这篇文章主要介绍了java背包问题动态规划算法分析,想了解算法的同学一定要看一下
    2021-04-04
  • Mybatis Generator自动生成对应文件的实现方法

    Mybatis Generator自动生成对应文件的实现方法

    这篇文章主要介绍了Mybatis Generator自动生成对应的文件的实现方法,需要的朋友可以参考下
    2017-09-09
  • java 百度手写文字识别接口配置代码

    java 百度手写文字识别接口配置代码

    本文通过实例代码给大家介绍了java 百度手写文字识别接口配置方法,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2022-01-01
  • java连接MySQL数据库实现代码

    java连接MySQL数据库实现代码

    这篇文章主要为大家详细介绍了java连接MySQL数据库实现代码,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • 你知道怎么用Spring的三级缓存解决循环依赖吗

    你知道怎么用Spring的三级缓存解决循环依赖吗

    这篇文章主要为大家详细介绍了Spring的三级缓存解决循环依赖,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • 详解Struts2中配置默认Action的方法

    详解Struts2中配置默认Action的方法

    本篇文章主要介绍了详解Struts2中配置默认Action的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • SpringMVC请求流程源码解析

    SpringMVC请求流程源码解析

    这篇文章主要介绍了SpringMVC请求流程源码分析,包括springmvc使用,SpringMVC启动过程及SpringMVC请求过程,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-07-07

最新评论