关于Java后台 HTML+CSS3 转换生成PDF文件问题求助!

关于Java后台 HTML+CSS3 转换生成PDF文件问题求助!

公司需求:HTML+CSS3(CSS样式是直接写在HTML文件当中)转换为PDF文件,并上传阿里云OSS供用户下载

  • 本身这个需求并不难,功能做完后不管是PDF质量还是生成速度都还不错,其中也遇到某些CSS样式不支持的问题,都用其他支持的样式替代

  • 接下来问题就出现了,文本中突然出现竖行文本CSS样式标签为:writing-mode,生成的PDF中文本并没有竖行显示,明显是itext解析时并不认识这个标签。

  • 由于业务逻辑要求,不可采用控制文本区宽度强制文字换行和其他物理方式来实现,目前查了大量资料,所有在HTML转换PDF这个问题上,对CSS都不太友好。

  • 后试过用Java调用虚拟打印机、先转word在转pdf、wkhtmltopdf、html2pdf等均没成功

  • 总结来说当html中出现竖行文本时,转换PDF希望所见即所得。

  • 现在求助有这方面经验的大神能给点解决思路,或者实现方式,小弟在此不胜感激,后面附上源码。

	
	  
		org.freemarker  
		freemarker  
		2.3.23  
	  
	
	
		org.apache.pdfbox
		pdfbox
		2.0.2
	
	
	
		org.xhtmlrenderer
		flying-saucer-pdf-itext5
		9.1.6
	
	
	
		net.sf.jtidy
		jtidy
		r938
	
	
	
		com.aliyun.oss
		aliyun-sdk-oss
		2.7.0
	
	@Override
	public void createPDF(HttpServletRequest request,String bookId) {
		
		Book book = bookDao.get(bookId);
		List> listProvider = bookHtmlDao.getProviderBy(bookId);
		bookEditionDao.updateEditionNo(bookId, "1");
		String providerName = listProvider.get(0).get("PROVIDER_NAME").toString();
		String providerId = listProvider.get(0).get("PROVIDER_ID").toString();
	
		// 初始化目录地址
		String ftlPath = request.getSession().getServletContext().getRealPath("/WEB-INF/classes/cn/jointat/mfb/service/toPDF");
		String ftlName = "hzSur";
		String outputPath = "D:/diskPDF/"+providerId+"_"+providerName+"/"+book.getBookName()+"/"+ftlName;
		
		// 有水印跟无水印版本分文件夹存
		String watermarkYesPath = outputPath+"/watermarkYes";
		String watermarkNoPath = outputPath+"/watermarkNo";
		
		System.out.println("====>服务商 【"+providerName+"】 请求生成PDF");
		System.out.println("========================= PDF开始生成 【"+book.getBookName()+"】 =========================");
		// 遍历Html代码块集合
		List listBookHtml = bookHtmlDao.getBookHtml(bookId);
		List filesInFolder = new ArrayList();
		for (int i = 0; i < listBookHtml.size(); i++) {
			String htmlString = listBookHtml.get(i).getHtmlContent();		//书页html内容
			// 将图片oss地址转换为内网地址
	        	htmlString = htmlString.replace("oss-cn-hangzhou.aliyuncs.com", "oss-cn-hangzhou-internal.aliyuncs.com");
			String outputName = book.getBookName()+"_"+(i+1);
			// 组装待合并的PDF路径
			filesInFolder.add(outputName+".pdf");
			
			// 有水印版本
			if(!PDFUtil.createPDF(ftlPath, ftlName, watermarkYesPath, outputName, htmlString, true)) {
				System.out.println("====>出现异常,导致错误的原因可能是html源码格式错误或模板错误,请联系管理员。");
			}
			// 无水印版本
			if(!PDFUtil.createPDF(ftlPath, ftlName, watermarkNoPath, outputName, htmlString, false)) {
				System.out.println("====>出现异常,导致错误的原因可能是html源码格式错误或模板错误,请联系管理员。");
			}
			System.out.println("====>第 【"+(i+1)+"】 张生成完成");
			// 封面页PDF生成图片base64
			if(i==0) {
				String base64 = PDFUtil.transPDFBase64(watermarkNoPath,outputName, 20);
				book.setBookLogoImg(base64);
				bookDao.update(book);
			}
		}

		System.out.println("====>开始合并");
		PDFUtil.mergePDF(watermarkYesPath, filesInFolder, book.getBookName()+"_清样.pdf");
		PDFUtil.mergePDF(watermarkNoPath, filesInFolder, book.getBookName()+"_原稿.pdf");
		System.out.println("========================= PDF结束生成 【"+book.getBookName()+"】 =========================");
		
		// 得到本地合并后的pdf路径
		String editionDownloadUrlYes = watermarkYesPath+"/"+book.getBookName()+"_清样.pdf";
		String editionDownloadUrlNo = watermarkNoPath+"/"+book.getBookName()+"_原稿.pdf";
		
		// 清样上传到阿里云oss
		System.out.println("====>清样上传到阿里云oss");
		String keyYes = "generatePDF/"+providerId+"_"+providerName+"/"+ftlName+"/Watermarks/"+book.getBookName()+"_清样.pdf";
		File fileYes = new File(editionDownloadUrlYes);
		Map mapYes = OssUtil.uploadFileOss("jointat-generate", keyYes, fileYes);
		
		// 原稿上传到阿里云oss
		System.out.println("====>原稿上传到阿里云oss");
		String keyNo = "generatePDF/"+providerId+"_"+providerName+"/"+ftlName+"/Manuscript/"+book.getBookName()+"_原稿.pdf";
		File fileNo = new File(editionDownloadUrlNo);
		Map mapNo = OssUtil.uploadFileOss("jointat-generate", keyNo, fileNo);
		
		// 更新PDF为可下载状态、下载地址
		String linkYes = mapYes.get("link").toString();
		String linkNo = mapNo.get("link").toString();
		if(!linkYes.equals("false") && !linkNo.equals("false")) {
			System.out.println("====>更新谱书为可下载状态");
			bookEditionDao.updateEditionYes(bookId, "1", linkYes, linkNo);
		}
		
		// 删除文件夹
		PDFUtil.delAllFile(watermarkYesPath);
		PDFUtil.delAllFile(watermarkNoPath);
	}

	 * html生成pdf
	 * @param ftlPath 		ftl模板目录路径
	 * @param ftlName		ftl模板名称
	 * @param outputPath		pdf输出路径
	 * @param outputName		pdf输出名称
	 * @param htmlString		html源码
	 * @param watermark		是否添加水印【true-添加、false=不添加】
	 * @return
	public static boolean createPDF(String ftlPath,String ftlName,String outputPath,String outputName,String htmlString,boolean watermark) {

		FileOutputStream os = null;
		try {
			// 创建一个freemarker.template.Configuration实例,它是存储 FreeMarker 
			Configuration cf = new Configuration(Configuration.VERSION_2_3_22);  								// 指定版本号
	        	cf.setDirectoryForTemplateLoading(new File(ftlPath));  	   											// 设置模板目录 
	        	cf.setDefaultEncoding("UTF-8");  																	// 设置默认编码格式
	        	Template temp = cf.getTemplate(ftlName+".ftl"); 													// 从设置的目录中获得模板 
	      
	        	// html转换为xhtml
			ByteArrayInputStream inputStream = new ByteArrayInputStream(htmlString.getBytes("UTF-8"));
	        	ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
	        
		        // 使用jtidy解析
		        Tidy tidy = new Tidy();							// 实例化Tidy对象
		        tidy.setInputEncoding("UTF-8");						// 设置输入
		        tidy.setQuiet(false);							// 如果是true 不输出注释,警告和错误信息
		        tidy.setShowWarnings(false);						// 不显示警告信息
		        tidy.setIndentContent(false);						// 缩进适当的标签内容。
		        tidy.setSmartIndent(false);						// 内容缩进
		        tidy.setIndentAttributes(false);
		        tidy.setPrintBodyOnly(true);						// 只输出body内部的内容
		        tidy.setWraplen(1024);							// 多长换行
		        tidy.setXHTML(true);							// 输出为xhtml
		        tidy.setTrimEmptyElements(false);               			// 不输出空元素
		        tidy.setMakeClean(false);						// 去掉没用的标签
		        tidy.setWord2000(false);						// 清洗word2000的内容
		        tidy.setErrout(new PrintWriter(System.out));				// 设置错误输出信息
		        tidy.parse(inputStream, outputStream);

			// 从模板生成html文件
			String fileHtml = "hzSur.html";
			File file = new File(fileHtml);
		        if (!file.exists()) {  
		            file.createNewFile();  
		        }  
	        
		        // 是否构造水印模板
		        String htmlWatermark = "";
		        if(watermark) {
		        	htmlWatermark = "
"; for (int i = 0; i < 10; i++) { htmlWatermark += "
"; } htmlWatermark +="
"; } // 将数据写入模板 Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),"UTF-8")); Map product = new HashMap(); product.put("htmlWatermark", htmlWatermark); product.put("htmlString", outputStream.toString()); temp.process(product, out); out.close(); // 定义输出目录路径及文件名称 File outDir =new File(outputPath); outDir.mkdirs(); ITextRenderer renderer = new ITextRenderer(); os = new FileOutputStream(outputPath+"/"+outputName+".pdf"); renderer.setDocument(new File(fileHtml).toURI().toURL().toString()); // 获取中文字体 ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont(ftlPath+"/MSYH.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); fontResolver.addFont(ftlPath+"/SIMSUN.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); fontResolver.addFont(ftlPath+"/SIMSUN.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); fontResolver.addFont(ftlPath+"/STKAITI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); fontResolver.addFont(ftlPath+"/SIMLI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); fontResolver.addFont(ftlPath+"/simfang.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); fontResolver.addFont(ftlPath+"/FZSTK.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); fontResolver.addFont(ftlPath+"/FZYTK.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); fontResolver.addFont(ftlPath+"/simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); fontResolver.addFont(ftlPath+"/SIMYOU.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 输出 renderer.layout(); renderer.createPDF(os); renderer.finishPDF(); renderer = null; os.close(); return true; } catch (Exception e) { System.out.println(e); e.printStackTrace(); return false; } }

你可能感兴趣的:(求助,JAVA,求助,HTML+CSS3,转换PDF,生成PDF)