Aspose.PDF for Java(实现PDF转Word无水印无页数限制)
文章目录文章目录前言Aspose.PDF for Java — PDF 转 Word 完整技术方案一、方案概述二、Maven 依赖配置三、License 授权配置方案 A永久授权推荐生产环境方案 B按量计费 Metered License适合初期低成本启动四、核心转换代码4.1 基础转换 Service4.2 转换参数优化提升质量的关键配置4.3 与 SpringBoot Controller 集成五、成本分析5.1 授权费用对比5.2 对你的产品的成本估算六、部署架构七、注意事项八、总结建议license破解方法一使用破解的license.xml文件进行授权同时通过代码移除生成文档中的水印示例代码license.xmlpom.xml方法二通过修改aspose-pdf的jar包使用javassist修改ADocument类的两个方法限制转换页数和水印jar包破解1、pom文件2、破解代码CtrlC/V修改一下路径直接运行也可以直接丢给AI让其自动完成3、代码实现示例总结前言Aspose.PDF 是一个 Java 组件旨在允许开发人员以编程方式即时创建简单或复杂的 PDF 文档。Aspose.PDF for Java 允许开发人员在 PDF 文档中插入表格、图形、图像、超链接、自定义字体等。此外还可以压缩 PDF 文档。Aspose.PDF for Java 提供出色的安全功能以开发安全的 PDF 文档。而 Aspose.PDF for Java 最显著的特点是它支持通过 API 和从 XML 模板创建 PDF 文档。提示以下是本篇文章正文内容下面案例可供参考Aspose.PDF for Java — PDF 转 Word 完整技术方案一、方案概述项目说明技术选型Aspose.PDF for Java纯 Java无需额外环境最新版本25.3截至 2025 年转换质量★★★★★ — 排版还原度极高支持表格、图片、复杂布局中文支持★★★★★ — 完美支持中文、中英混排集成难度★★★★★ — 纯 Java 依赖与 SpringBoot 无缝集成授权方式永久授权 $1,199 起 / 按量计费Metered License二、Maven 依赖配置Aspose 未将所有版本发布到 Maven 中央仓库需手动添加其私有仓库。pom.xmlXMLproperties aspose.pdf.version25.3/aspose.pdf.version /properties repositories repository idaspose-repo/id nameAspose Java API Repository/name urlhttps://releases.aspose.com/java/repo//url /repository /repositories dependencies dependency groupIdcom.aspose/groupId artifactIdaspose-pdf/artifactId version${aspose.pdf.version}/version /dependency /dependencies三、License 授权配置方案 A永久授权推荐生产环境购买后将Aspose.PDF.lic文件放入src/main/resources/license/目录。JavaComponent public class AsposeLicenseConfig { PostConstruct public void init() { try { License license new License(); // 从 classpath 加载 license 文件 InputStream is getClass() .getClassLoader() .getResourceAsStream(license/Aspose.PDF.lic); if (is ! null) { license.setLicense(is); log.info(Aspose.PDF License 加载成功); } else { log.warn(未找到 Aspose.PDF License 文件将使用评估模式有水印); } } catch (Exception e) { log.error(Aspose.PDF License 加载失败, e); } } }方案 B按量计费 Metered License适合初期低成本启动JavaComponent public class AsposeMeteredLicenseConfig { PostConstruct public void init() { try { Metered metered new Metered(); // 使用你在 Aspose 官网申请的公钥和私钥 metered.setMeteredKey( 你的公钥-public-key, 你的私钥-private-key ); log.info(Aspose.PDF Metered License 加载成功); } catch (Exception e) { log.error(Metered License 加载失败, e); } } }Metered License 优势按实际转换量计费初期用户量小时成本极低随业务增长自动扩展无需一次性投入。四、核心转换代码4.1 基础转换 ServiceJavaService Slf4j public class PdfToWordService { /** * PDF 转 WordDOCX * * param pdfFilePath 输入 PDF 文件路径 * param outputDir 输出目录 * return 转换后的 DOCX 文件路径 */ public String convertPdfToWord(String pdfFilePath, String outputDir) { long startTime System.currentTimeMillis(); try { // 1. 加载 PDF 文档 Document pdfDocument new Document(pdfFilePath); // 2. 设置转换参数优化转换质量 DocSaveOptions saveOptions new DocSaveOptions(); saveOptions.setFormat(DocSaveOptions.DocFormat.DocX); // 识别列表/表格结构提升排版还原度 saveOptions.setRecognizeListItems(true); // 相对对齐优化 saveOptions.setRelativeHorizontalProximity(2.5f); // 模式增强排版还原 saveOptions.setMode(DocSaveOptions.RecognitionMode.TextBoxFlow); // 3. 生成输出文件名 String fileName FilenameUtils.getBaseName(pdfFilePath) .docx; String outputPath outputDir File.separator fileName; // 4. 执行转换 pdfDocument.save(outputPath, saveOptions); pdfDocument.close(); long cost System.currentTimeMillis() - startTime; log.info(PDF转Word完成耗时: {}ms文件: {}, cost, outputPath); return outputPath; } catch (Exception e) { log.error(PDF转Word失败文件: {}, pdfFilePath, e); throw new RuntimeException(PDF转Word转换失败: e.getMessage()); } } }4.2 转换参数优化提升质量的关键配置Java/** * 根据不同 PDF 类型选择最优转换策略 */ public String convertWithStrategy(String pdfFilePath, String outputDir, ConvertStrategy strategy) { Document pdfDocument new Document(pdfFilePath); DocSaveOptions saveOptions new DocSaveOptions(); saveOptions.setFormat(DocSaveOptions.DocFormat.DocX); switch (strategy) { case HIGH_FIDELITY: // 高保真模式最大程度还原排版适合复杂排版的 PDF saveOptions.setMode(DocSaveOptions.RecognitionMode.TextBoxFlow); saveOptions.setRecognizeListItems(true); saveOptions.setRelativeHorizontalProximity(2.5f); break; case TEXT_FOCUS: // 文本优先模式牺牲部分排版提升文本提取准确度适合扫描件 saveOptions.setMode(DocSaveOptions.RecognitionMode.PureTextBox); break; case FAST: // 快速模式转换速度最快适合简单 PDF saveOptions.setMode(DocSaveOptions.RecognitionMode.TextBoxFlow); saveOptions.setRecognizeListItems(false); break; default: saveOptions.setMode(DocSaveOptions.RecognitionMode.TextBoxFlow); } String outputPath outputDir File.separator FilenameUtils.getBaseName(pdfFilePath) .docx; pdfDocument.save(outputPath, saveOptions); pdfDocument.close(); return outputPath; } public enum ConvertStrategy { HIGH_FIDELITY, // 高保真默认推荐 TEXT_FOCUS, // 文本优先 FAST // 快速转换 }4.3 与 SpringBoot Controller 集成JavaRestController RequestMapping(/api/convert) Slf4j public class ConvertController { Autowired private PdfToWordService pdfToWordService; Autowired private FileStorageService fileStorageService; /** * PDF 转 Word 接口 */ PostMapping(/pdf-to-word) public ResultConvertResultVO convertPdfToWord( RequestParam(file) MultipartFile file, RequestParam(value strategy, defaultValue HIGH_FIDELITY) ConvertStrategy strategy) { // 1. 校验文件 if (file.isEmpty()) { return Result.fail(文件不能为空); } String originalName file.getOriginalFilename(); if (!originalName.toLowerCase().endsWith(.pdf)) { return Result.fail(仅支持 PDF 格式文件); } // 2. 保存上传文件到临时目录 String pdfFilePath fileStorageService.saveTempFile(file); try { // 3. 执行转换 String outputDir fileStorageService.getTempOutputDir(); String docxFilePath pdfToWordService.convertWithStrategy( pdfFilePath, outputDir, strategy); // 4. 获取文件大小信息 File pdfFile new File(pdfFilePath); File docxFile new File(docxFilePath); ConvertResultVO result new ConvertResultVO(); result.setOutputFileName(FilenameUtils.getName(docxFilePath)); result.setOutputFileSize(docxFile.length()); result.setInputFileSize(pdfFile.length()); result.setOutputUrl(/files/download/ FilenameUtils.getName(docxFilePath)); return Result.success(result); } finally { // 5. 清理临时 PDF 文件转换结果保留 48 小时后自动清理 fileStorageService.scheduleDelete(pdfFilePath, 48); } } }五、成本分析5.1 授权费用对比授权类型费用适用场景评估版免费免费但输出有水印开发测试阶段Metered License按量约 $0.01-0.03/次转换初期上线、用户量不确定时Developer 永久授权1,199一次性399/年续订用户量大、长期运营Developer OEM3,597一次性1,199/年续订多部署点、SaaS 平台5.2 对你的产品的成本估算场景非会员每日 3 次免费假设 DAU 1000 日转换量 ≈ 1000 × 3 3,000 次/天 月转换量 ≈ 90,000 次/月 Metered License 成本 ≈ 90,000 × $0.02 ≈ $1,800/月约 ¥13,000/月 永久授权成本 ≈ $1,199 $399/年 ≈ ¥11,500 首年无限次建议当月转换量超过60,000 次时永久授权比按量计费更划算。六、部署架构┌─────────────┐ ┌──────────────────┐ ┌─────────────┐ │ 微信小程序 │────▶│ SpringBoot 后端 │────▶│ MinIO │ │ (文件上传) │ │ Aspose.PDF 转换 │ │ (文件存储) │ └─────────────┘ └──────────────────┘ └─────────────┘ │ ┌──────┴──────┐ │ MySQL │ │ (记录/用户) │ └─────────────┘优势纯 Java 方案无需额外部署 Python 或 LibreOffice 环境运维简单。七、注意事项项目说明评估水印未配置 License 时转换结果会有 Evaluation Only 水印上线前必须配置正式 LicenseJDK 版本Aspose.PDF 25.x 要求 JDK 8推荐 JDK 17内存消耗大 PDF 文件50MB转换时内存占用较高建议设置 JVM 参数-Xmx512m并限制上传文件大小异步处理转换耗时较长时5 秒建议使用Async异步执行避免阻塞 HTTP 线程文件清理转换完成后临时文件需定时清理建议保留 48 小时八、总结建议阶段授权方案理由开发/测试评估版免费验证功能有水印不影响开发MVP 上线Metered License按量用户量不确定按实际用量付费降低初期成本用户量稳定后购买 Developer 永久授权月转换量 6 万次时永久授权更经济Sources:Aspose.PDF for Java 官方安装文档Aspose.PDF License 配置教程Metered License 按量计费指南Aspose.PDF 定价页面PDF 转 DOCX 完整教程来到重点部分请看大屏幕license破解方法一使用破解的license.xml文件进行授权同时通过代码移除生成文档中的水印示例代码public class PDFHelper3 { public static void main(String[] args) throws Exception { ClassPathResource classPathResource new ClassPathResource(license.xml); //调用授权方法 InputStream is classPathResource.getInputStream(); License license new License(); license.setLicense(is); pdf2doc(G:\\logs\\2022草稿3.pdf); //modifyPDFJar(); } //移除文字水印 public static boolean removeWatermark(File file) { try { XWPFDocument doc new XWPFDocument(new FileInputStream(file)); // 段落 ListXWPFParagraph paragraphs doc.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { String textparagraph.getText(); if(Evaluation Only. Created with Aspose.PDF. Copyright 2002-2021 Aspose Pty Ltd..equals(text)){ ListXWPFRun runs paragraph.getRuns(); runs.forEach(e- e.setText(,0)); } } FileOutputStream outStream new FileOutputStream(file); doc.write(outStream); outStream.close(); } catch (IOException e) { e.printStackTrace(); } return true; } //pdf转doc public static void pdf2doc(String pdfPath) { long old System.currentTimeMillis(); try { //新建一个doc文档 String wordPathpdfPath.substring(0,pdfPath.lastIndexOf(.)).docx; File file new File(wordPath); FileOutputStream os new FileOutputStream(file); //Address是将要被转化的word文档 Document doc new Document(pdfPath); //全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换 doc.save(os, SaveFormat.DocX); os.close(); //去除水印 removeWatermark(new File(wordPath)); //转化用时 long now System.currentTimeMillis(); System.out.println(Pdf 转 Word 共耗时 ((now - old) / 1000.0) 秒); } catch (Exception e) { System.out.println(Pdf 转 Word 失败...); e.printStackTrace(); } } //pdf转excel public static void pdf2Excel(String pdfPath) { long old System.currentTimeMillis(); try { //新建一个excel文档 String wordPathpdfPath.substring(0,pdfPath.lastIndexOf(.)).xls; File file new File(wordPath); FileOutputStream os new FileOutputStream(file); //Address是将要被转化的word文档 Document doc new Document(pdfPath); //全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换 doc.save(os, SaveFormat.Excel); os.close(); //去除水印 removeWatermark(new File(wordPath)); //转化用时 long now System.currentTimeMillis(); System.out.println(Pdf 转 excel 共耗时 ((now - old) / 1000.0) 秒); } catch (Exception e) { System.out.println(Pdf 转 excel 失败...); e.printStackTrace(); } } }license.xmlLicense Data Products ProductAspose.Total for Java/Product ProductAspose.Words for Java/Product /Products EditionTypeEnterprise/EditionType SubscriptionExpiry20991231/SubscriptionExpiry LicenseExpiry20991231/LicenseExpiry SerialNumber8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7/SerialNumber /Data Signature sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppod0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU /Signature /Licensepom.xml?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdcom.youfa/groupId artifactIdpdfForWord/artifactId version1.0.0/version namepdfForWord/name descriptionpdfForWord/description properties java.version1.8/java.version project.build.sourceEncodingUTF-8/project.build.sourceEncoding project.reporting.outputEncodingUTF-8/project.reporting.outputEncoding spring-boot.version2.3.7.RELEASE/spring-boot.version /properties repositories repository idAsposeJavaAPI/id nameAspose Java API/name urlhttps://repository.aspose.com/repo//url /repository /repositories dependencies dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.1.4/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.30/version optionaltrue/optional /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope exclusions exclusion groupIdorg.junit.vintage/groupId artifactIdjunit-vintage-engine/artifactId /exclusion /exclusions /dependency !-- 使用本地aspose-pdf jar包 -- dependency groupIdcom.aspose/groupId artifactIdaspose-pdf/artifactId version21.11/version /dependency !-- poi-ooxml是poi的升级版本-- dependency groupIdorg.apache.poi/groupId artifactIdpoi-ooxml/artifactId version4.1.2/version /dependency dependency groupIdorg.javassist/groupId artifactIdjavassist/artifactId version3.28.0-GA/version /dependency /dependencies dependencyManagement dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-dependencies/artifactId version${spring-boot.version}/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.8.1/version configuration source1.8/source target1.8/target encodingUTF-8/encoding /configuration /plugin plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId version2.3.7.RELEASE/version configuration mainClasscom.youfa.pdfforword.PdfForWordApplication/mainClass /configuration executions execution idrepackage/id goals goalrepackage/goal /goals /execution /executions /plugin /plugins /build /projectPDFHelper3.java 使用 license.setLicense(is) 加载license.xml授权文件实现了PDF转Word和Excel的功能通过 removeWatermark 方法手动移除生成文档中的水印注释掉了 modifyPDFJar() 方法说明可能曾经考虑过jar包破解方式license.xml 包含Aspose.Total for Java和Aspose.Words for Java的授权信息授权到期时间为2099年12月31日包含序列号和签名pom.xml 依赖了aspose-pdf 21.11版本包含了javassist依赖可能用于jar包破解但当前未使用配置了Aspose的Maven仓库方法二通过修改aspose-pdf的jar包使用javassist修改ADocument类的两个方法限制转换页数和水印jar包破解1、pom文件分别复制进pom文件记得配置maven的中央仓库在settings.xml中 配置单独的仓库地址 repositories repository idAsposeJavaAPI/id nameAspose Java API/name urlhttps://repository.aspose.com/repo//url /repository /repositories 相关依赖 dependency groupIdorg.javassist/groupId artifactIdjavassist/artifactId version3.20.0-GA/version /dependency !-- https://mvnrepository.com/artifact/com.aspose/aspose-pdf -- dependency groupIdcom.aspose/groupId artifactIdaspose-pdf/artifactId version21.8/version /dependency2、破解代码CtrlC/V修改一下路径直接运行也可以直接丢给AI让其自动完成import cn.comingnet.app.bean.JumpInfo; import cn.comingnet.app.bean.SchemeDto; import cn.comingnet.common.util.HttpClientUtils; import cn.comingnet.common.util.Jsons; import cn.comingnet.common.util.StringUtil; import cn.comingnet.front.constants.BaseConst; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.aspose.pdf.Document; import com.aspose.pdf.SaveFormat; import com.aspose.pdf.internal.imaging.internal.Exceptions.IO.FileNotFoundException; import javassist.*; import org.apache.batik.i18n.LocaleGroup; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.apache.log4j.helpers.LogLog; import org.junit.Test; import java.io.*; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; public class Demo { public static void main(String[] args) throws Exception { //找到自己的maven仓库这个jar包对应的路径替换掉别的不需要动 String jarPath E:\\maven\\mvnRepository\\com\\aspose\\aspose-pdf\\21.8\\aspose-pdf-21.8.jar; crack(jarPath); } private static void crack(String jarName) { try { ClassPool.getDefault().insertClassPath(jarName); CtClass ctClass ClassPool.getDefault().getCtClass(com.aspose.pdf.ADocument); CtMethod[] declaredMethods ctClass.getDeclaredMethods(); int num 0; for (int i 0; i declaredMethods.length; i) { if (num 2) { break; } CtMethod method declaredMethods[i]; CtClass[] ps method.getParameterTypes(); if (ps.length 2 method.getName().equals(lI) ps[0].getName().equals(com.aspose.pdf.ADocument) ps[1].getName().equals(int)) { // 最多只能转换4页 处理 System.out.println(method.getReturnType()); System.out.println(ps[1].getName()); method.setBody({return false;}); num 1; } if (ps.length 0 method.getName().equals(lt)) { // 水印处理 method.setBody({return true;}); num 2; } } File filenew File(jarName); ctClass.writeFile(file.getParent()); disposeJar(jarName, file.getParent()/com/aspose/pdf/ADocument.class); } catch(NotFoundException e){ e.printStackTrace(); } catch(CannotCompileException e){ e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private static void disposeJar(String jarName, String replaceFile) { ListString deletes new ArrayList(); deletes.add(META-INF/37E3C32D.SF); deletes.add(META-INF/37E3C32D.RSA); File oriFile new File(jarName); if (!oriFile.exists()) { System.out.println(######Not Find File: jarName); return; } //将文件名命名成备份文件 String bakJarName jarName.substring(0, jarName.length() - 3) cracked.jar; // File bakFilenew File(bakJarName); try { //创建文件根据备份文件并删除部分 JarFile jarFile new JarFile(jarName); JarOutputStream jos new JarOutputStream(new FileOutputStream(bakJarName)); Enumeration entries jarFile.entries(); while (entries.hasMoreElements()) { JarEntry entry (JarEntry) entries.nextElement(); if (!deletes.contains(entry.getName())) { if (entry.getName().equals(com/aspose/pdf/ADocument.class)) { System.out.println(Replace:------- entry.getName()); JarEntry jarEntry new JarEntry(entry.getName()); jos.putNextEntry(jarEntry); FileInputStream fin new FileInputStream(replaceFile); byte[] bytes readStream(fin); jos.write(bytes, 0, bytes.length); } else { jos.putNextEntry(entry); byte[] bytes readStream(jarFile.getInputStream(entry)); jos.write(bytes, 0, bytes.length); } } else { System.out.println(Delete:------- entry.getName()); } } jos.flush(); jos.close(); jarFile.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } private static byte[] readStream(InputStream inStream) throws Exception { ByteArrayOutputStream outSteam new ByteArrayOutputStream(); byte[] buffer new byte[1024]; int len -1; while ((len inStream.read(buffer)) ! -1) { outSteam.write(buffer, 0, len); } outSteam.close(); inStream.close(); return outSteam.toByteArray(); } }运行上面的主方法破解成功后会再同级文件夹下生成一个aspose-pdf-21.11.cracked.jar包用这个包替换原来的aspose-pdf-21.11.jar包即可。提示想要jar包可联系博主jar包只能私发3、代码实现示例public class Demo { //放入一个pdf的路径 public static void main(String[] args) throws IOException { pdf2doc(D:\\浏览器下载\\edg\\1_20221130145105.pdf); } //pdf转doc public static void pdf2doc(String pdfPath) { long old System.currentTimeMillis(); try { //新建一个word文档 String wordPathpdfPath.substring(0,pdfPath.lastIndexOf(.)).docx; FileOutputStream os new FileOutputStream(wordPath); //doc是将要被转化的word文档 Document doc new Document(pdfPath); //全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换 doc.save(os, SaveFormat.DocX); os.close(); //转化用时 long now System.currentTimeMillis(); System.out.println(Pdf 转 Word 共耗时 ((now - old) / 1000.0) 秒); } catch (Exception e) { System.out.println(Pdf 转 Word 失败...); e.printStackTrace(); } } }OK总结方法一采用了license.xml授权 手动移除水印的方式。这种方式虽然配置简单但可能存在授权有效性的风险。优势 使用license.xml授权方式更简单不需要修改jar包局限性 生成的文档仍会有水印需要通过代码手动移除license.xml的有效性可能会受到Aspose官方的验证方法二需要修改jar包操作较复杂优势 直接修改jar包中的类方法从根本上禁用水印和页数限制博主提醒条件允许还是要支持正版不能使用第三方工具进行破解