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
来捕获常见的异常,如 IOException
、DocumentException
等,并返回 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标签的资料请关注脚本之家其它相关文章!
相关文章
Mybatis Generator自动生成对应文件的实现方法
这篇文章主要介绍了Mybatis Generator自动生成对应的文件的实现方法,需要的朋友可以参考下2017-09-09
最新评论