当前位置: 首页 > news >正文

java对电子发票是否原件的快速检查

快速检查上传的电子发票是否为原件

需求背景

现在财务要求报销的时候,必须得是下载的pdf原件,不允许是手机拍照,或者通过扫描件软件进行扫描,然后上传报销。

开发分析

文本可提取性检查:

原始电子发票 PDF 的文字是可复制的,而扫描件本质是图片,无法直接提取文本。

作为开发而言,其实只要找到发票号,进而通过文本提取,然后判断发票号是否存在即可。大佬给提供的思路【发票不是有发票号嘛,用发票号在这个pdf搜索,能搜出来就认为是正常的版式文件,搜不出来就是扫描得,或者图片喽】

对此进行分析:
1、首先引入pdf解析依赖,主要是读取pdf上的文字。

<dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.27</version>
</dependency>

2、设计一个util类,用于封装具体的操作过程:

/*** 检测 PDF 是否为扫描件或拍照件* 支持传入发票号进行文本可搜索性验证*/
public class InvoiceCheckUtil {/*** 检测 PDF 是否为扫描件/拍照件** @param filePath   PDF 文件路径* @param invoiceNum 发票号码(用于验证是否可搜索)* @return true = 电子发票原件*/public static boolean checkOriginalElectronicInvoice(String filePath, String invoiceNum) {File file = new File(filePath);if (!file.exists() || !file.isFile()) {throw new IllegalArgumentException("文件不存在或无效: " + filePath);}try (PDDocument document = PDDocument.load(file)) {if (document.getNumberOfPages() == 0) {//空文件return false;}String fullText = new PDFTextStripper().getText(document);// 清理文本:去除换行、制表符等 改为空格String cleanedText = fullText.replaceAll("\\s+", " ");// 如果发票号在文本中找不到 → 极可能是扫描件if (!cleanedText.contains(invoiceNum)) {return false; // 找不到发票号 → 不是原件}// 找到了发票号 → 是原始电子发票return true;} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e.getMessage());}}

3、测试

    public static void main(String[] args) {String filePath = "D:\\fe794cc19af6589f.pdf";String invoiceNum = "25952000000162481528"; // 示例发票号try {boolean flag = checkOriginalElectronicInvoice(filePath, invoiceNum);System.out.println("电子发票原件?:" + flag);} catch (Exception e) {e.printStackTrace();}}

到此完成一个简易版的判断pdf是否 不是原件的操作。

总结

这是一种带着发票号做原件检查的操作,适合已经通过OCR识别到了一些内容,反手检查上传文件的操作。

http://www.dtcms.com/a/388837.html

相关文章:

  • 贪心算法应用:顶点覆盖问题详解
  • Odoo中非库存商品的高级自动化采购工作流程
  • 缺少自动化测试会对 DevOps 带来哪些风险
  • 深入解析 Python 中的 __pycache__与字节码编译机制
  • SEO 优化:元数据 (Metadata) API 和站点地图 (Sitemap) 生成
  • postman+Jenkins进行API automation集成
  • 【算法磨剑:用 C++ 思考的艺术・单源最短路收官】BF/SPFA 负环判断模板 + 四大算法全总结
  • Flink的介绍及应用
  • 微信小程序插屏广告(InterstitialAd)全解析与实战应用案例
  • 格雷希尔G70R系列快速密封连接器+GT系列软管组件的配套组合方案,在新能源汽车老化测试的应用
  • 【Debug日志| 随机下降】
  • 滑动窗口法的优化与实战——力扣209.长度最小的子数组
  • 【Spring Boot 报错已解决】org.yaml.snakeyaml.scanner.ScannerException 报错原因与解决方案
  • 国家统计局数据读取——数据读取——清洗数据06
  • 基于 scratch 构建简单镜像
  • Web安全的暗角:10大易忽略逻辑漏洞解析!
  • 矩阵奇异值分解算法(SVD)详解
  • 【FreeRTOS】 二值信号量与互斥量(CMSIS-RTOS v2 版本)
  • Qt C++ :Qt全局定义<QtGlobal>
  • 【STL源码剖析】从源码看 list:从迭代器到算法
  • MySQL 专题(三):事务与锁机制深度解析
  • 使用BLIP训练自己的数据集(图文描述)
  • Geoserver修行记--在geoserver中如何复制某个图层组内容
  • DBG数据库透明加密网关:SQLServer应用免改造的安全防护方案,不限制开发语言的加密网关
  • 不同上位开发语言、PLC下位平台、工业协议与操作系统平台下的数据类型通用性与差异性详解
  • 【入门篇|第二篇】从零实现选择、冒泡、插入排序(含对数器)
  • javaweb Servlet基本介绍及开发流程
  • MySQL MHA高可用
  • 整体设计 逻辑拆解之2 实现骨架:一元谓词+ CNN的谓词系统
  • SpEL(Spring Expression Language)学习笔记