目录
前言: 将 HTML 字符串(带图片)转换成 PDF 文件,可以使用 Flying Saucer 或者 iText 等第三方库。
(注)以下依赖是:
Gradle依赖坐标、用Maven的可以去官网查询、官网:https://mvnrepository.com/
存储PDF文件到本地:
存储PDF文件到服务器:
1)、iText第三方库依赖
2)、Flying Saucer第三方库依赖
一、以下是使用的 iText 库下、PDF转换
前言:
将 HTML 字符串(带图片)转换成 PDF 文件,可以使用 Flying Saucer 或者 iText 等第三方库。
(注)以下依赖是:
Gradle依赖坐标、用Maven的可以去官网查询、官网:https://mvnrepository.com/
存储PDF文件到本地:
iText库下的可以看:1.1和1.2代码实例
Flying Saucer库下的可以看:2.1和2.2代码实例
存储PDF文件到服务器:
iText库下的可以看:1.3代码实例
本项目中就使用了iText库进行写的PDF文件到服务器,所以就没有写Flying Saucer库下的实例方法了
使用的是Mino服务器
1)、iText第三方库依赖
implementation 'com.lowagie:itext:2.1.7'
implementation 'org.jsoup:jsoup:1.14.3'
implementation 'com.itextpdf:html2pdf:3.0.2'
implementation 'com.itextpdf:layout:7.1.18'
implementation 'com.itextpdf:kernel:7.1.16'
2)、Flying Saucer第三方库依赖
implementation 'org.xhtmlrenderer:flying-saucer-pdf-itext5:9.1.22'
一、以下是使用的 iText 库下、PDF转换
1.1)、当前方法只适用于,全是英文和数字的HTML的字符串时、我们直接上代码,简单易懂、
不过需要注意的是,你在应用第三方库是,导包一定要导入正确,否则会有一些方法是无法使用的。
注意:当前方法返回的PDF文件是存在本地的
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.font.FontProvider;
public static void main(String[] args) throws Exception {
// 适合英文格式、HTML转PDF文件
String html = "<html><head></head><body><h1>Hello World!</h1><p>This is an example of HTML to PDF conversion.</p></body></html>";
String pdfPath = "D:\\outputPDF.pdf";
// Convert HTML to PDF
File file = new File(pdfPath);
OutputStream outputStream = new FileOutputStream(file);
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDocument = new PdfDocument(writer);
ConverterProperties converterProperties = new ConverterProperties();
HtmlConverter.convertToPdf(html, pdfDocument, converterProperties);
// Close streams and document
pdfDocument.close();
outputStream.close();
}
1.2)、当前方法适用于中文和英文和数字的HTIM字符串、也是直接上代码,简单易懂、相信大家都能看的懂得、对应的包一定要导入正确,否则会报错呦!
注:此方法也是保存在本地的文件
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.font.FontProvider;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public static void main(String[] args) {
// 中文和英文的格式
String html = "<html><head></head><body><h1>Hello World!</h1><p>This is an example of HTML to PDF conversion. 中国大好河山</p></body></html>";
String pdfPath = "D:\\cumentPdf.pdf";
File file = new File(pdfPath);
try(OutputStream outputStream = new FileOutputStream(file)) {
// 转换 HTML to PDF
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDocument = new PdfDocument(writer);
// 设置PDF大小
pdfDocument.setDefaultPageSize(PageSize.A4);
// 设置中文
ConverterProperties converterProperties = new ConverterProperties();
FontProvider fontProvider = new DefaultFontProvider(true, true, true);
converterProperties.setFontProvider(fontProvider);
// html转换PDF
HtmlConverter.convertToPdf(html, pdfDocument, converterProperties);
// 关闭
pdfDocument.close();
} catch (Exception e){
e.fillInStackTrace();
}
}
1.3)、此方法是上传到Mino服务器的一个思路、上传到服务器具体的方法,如果使用根据当前的业务逻辑进行书写、没有写过Mino服务器上传的,我这边可以给出一个简单的例子来,如果有不适当的地方,请自行修改只仅供参考!
private final MinoFileServiceImpl minoFileService;
public TestService(MinoFileServiceImpl minoFileService) {
this.minoFileService = minoFileService;
}
public void kk(){
// 中文和英文的格式
String html = "<html><head></head><body><h1>Hello World!</h1><p>This is an example of HTML to PDF conversion. 中国大好河山</p></body></html>";
test2(html);
}
private void test2(String html){
// 获取文件标题
Element firstP = doc.selectFirst("p");
String textContent = firstP != null ? firstP.text() : "";
// 文件地址(文件名称)
String pdfPath = textContent + ".pdf";
try(ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
// 转换 HTML to PDF
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDocument = new PdfDocument(writer);
// 设置PDF大小
pdfDocument.setDefaultPageSize(PageSize.A4);
// 设置中文
ConverterProperties converterProperties = new ConverterProperties();
// 服务器上使用的中午字体文件字体文件(该/simsun.ttf文件需要下载、可以放在resources目录下)
InputStream inputStream = this.getClass().getResourceAsStream("/simsun.ttf");
byte[] bytes = ByteToMultipartFileConverterUtil.inputStreamToByteArray(inputStream);
FontProgram fontProgram = FontProgramFactory.createFont(bytes);
FontProvider fontProvider = new DefaultFontProvider(true, true, true);
fontProvider.addFont(fontProgram);
converterProperties.setFontProvider(fontProvider);
// html转换PDF
HtmlConverter.convertToPdf(html, pdfDocument, converterProperties);
// pdf文件流
byte[] pdfBytes = outputStream.toByteArray();
// byte转成 MultipartFile
MultipartFile multipartFile = ByteToMultipartFileConverterUtil.convert(pdfBytes, pdfPath);
// 文件上传(待上传的文件流、文件服务器的桶名称、路径)
minoFileService.uploadFile(multipartFile,"test",pdfPath);
// 关闭
pdfDocument.close();
} catch (Exception e){
e.fillInStackTrace();
}
}
以上的方法就是简单的将字符串HTML转成PDF然后再上传到Mino服务器上,方法当中的MinoFileServiceImpl这个是文件上传的如果没有文件上传的代码可以看下1.4这个。
1.4)、Mino服务器文件上传
这个方法就是在 MinoFileServiceImpl 里面的,在我们文件上传中需要用到的上传的方法
@Override
public boolean uploadFile(MultipartFile multipartFile,
String bucketName,
String filePath) {
try {
if (null == multipartFile || StringUtil.isEmpty(bucketName)) {
logger.error("error message: 未传入有效的文件 或 bucket");
return false;
}
logger.debug("debug message: 开始上传文件 <{}>", multipartFile);
String fileName = StringUtil.isEmpty(filePath) ? multipartFile.getOriginalFilename() : filePath;
// 默认上传至
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.stream(multipartFile.getInputStream(), multipartFile.getSize(), -1)
.contentType(multipartFile.getContentType()).build());
return true;
} catch (Exception e) {
logger.error("error message: 文件 <{}> 上传失败,原因是:", multipartFile, e);
return false;
}
}
1.5)、byte[]流转成MultipartFile流的方法
这个是一个util工具类ByteToMultipartFileConverterUtil这个工具类,在文件上传的时候需要将流进行转换然后再上传的文件服务器上,提供此方法可以拿来直接使用
以上1.3中使用到的这个ByteToMultipartFileConverterUtil工具类的两个方法都在这里、可以参考以下代码
public class ByteToMultipartFileConverterUtil {
private ByteToMultipartFileConverterUtil() {
}
public static MultipartFile convert(byte[] pdfBytes, String fileName) {
InputStream inputStream = new ByteArrayInputStream(pdfBytes);
return new MultipartFile() {
@NotNull
@Override
public String getName() {
return "file";
}
@Override
public String getOriginalFilename() {
return StringUtil.isEmpty(fileName) ? "file.pdf" : fileName;
}
@Override
public String getContentType() {
return "application/pdf";
}
@Override
public boolean isEmpty() {
return pdfBytes.length == 0;
}
@Override
public long getSize() {
return pdfBytes.length;
}
@NotNull
@Override
public byte[] getBytes() {
return pdfBytes;
}
@NotNull
@Override
public InputStream getInputStream() {
return inputStream;
}
@Override
public void transferTo(@NotNull java.io.File file) throws IllegalStateException {
throw new UnsupportedOperationException("MultipartFiles must not be manually written to disk");
}
};
}
public static byte[] inputStreamToByteArray(InputStream inputStream) throws IOException {
// 使用 DataInputStream 包装 InputStream
DataInputStream dis = new DataInputStream(inputStream);
// 获取 InputStream 的数据长度
int length = inputStream.available();
// 创建 byte[] 数组,存储 InputStream 的数据
byte[] bytes = new byte[length];
// 读取 InputStream 中的数据并存储到 byte[] 数组中
dis.readFully(bytes);
return bytes;
}
}
通过以上代码,我们将带有图片的 HTML 字符串转换成了 PDF 格式,并保存到了本地或服务器的 文件中。其中的中文部分使用了宋体字体,通过注册字体文件路径来加载字体。
当然,不同的 PDF 转换库的实现会有所不同,但是思路大致相似,都需要将 HTML 字符串通过某种方式转换为 PDF 格式。