需求
需要将pdf 上传到默默网站上,但是需要的是图片格式,有可能是一张有可能是多张,其他软件要么付费,要么免费的就几页其他的还不完整,气人不气人,
所以根据这个需求,进行一个java 版本的将pdf 转换为图片功能,尤其是文员的同事,最头痛了,每个月的会员费。
演示
选择一个pdf 文件
点击转图片
等待几秒就可以了。
也可以 使用main 方法
结果
多张
单张
实现方法
实现步骤 将pdf 转换本地,然后创建一个本地文件夹,用于放图片文件夹;
多图情况下,直接将文件夹打包下载下来就可以了。
单图情况下,将文件夹下的图片合并成一个图片,我发现这个单个图片和多张图片的下载包差不多大小。
所以单张图片的时候需要压缩一下。这个暂不说了。
然后再通过ZipOutputStream 转zip 就下载下载。
代码部分
通过templates 显示html
配置部分
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
显示html
@GetMapping()
public String index() {
return "index";
}
文件放入 如图
[图片上传失败...(image-968815-1693273073409)]
然后进行提交操作
<h3 >pdf 转图片 </h3>
<form th:action="@{/toImage}" th:method="post" enctype="multipart/form-data">
<input name="file" accept="application/pdf" type="file"/>
<input type="radio" name="page" value="one">单张
<input type="radio" name="page" checked value="multiple">多张 <br>
<br>
<br>
<input type="submit" value="转图片"><br>
</form>
然后是 toImage方法部分
@PostMapping("/toImage")
public void pdfToImage(@RequestParam("file") MultipartFile multipartFile, @RequestParam("page") String page, HttpServletResponse response) throws Exception {
....
}
方法里面有两个参数,一个是图片,一个是页面参数。 page 可能会有one 和multiple ,默认是multiple 这个,用的html checked 方法即可。
设置
response.setCharacterEncoding("UTF-8");
response.setContentType("multipart/form-data");
response.setHeader("content-disposition", "attachment;filename=" + "2023.zip");
这个2023.zip 是下载的文件名字,主要的是中文会乱码,这个就不讲怎么解决了。前端去修改也是一样的。
里面方法解说
/**
* @param multipartFile 文件
* @param page one单页,multipled多页
* @return
*/
@PostMapping("/toImage")
public void pdfToImage(@RequestParam("file") MultipartFile multipartFile, @RequestParam("page") String page, HttpServletResponse response) throws Exception {
// 设置
response.setCharacterEncoding("UTF-8");
response.setContentType("multipart/form-data");
response.setHeader("content-disposition", "attachment;filename=" + "2023.zip");
ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
// 获取统一的 文件夹名字 ,避免每次重复
String uuId = UUID.randomUUID().toString();
// 文件缓存的地方
String dstImgFolder = "F:/spring";
File fileFolder = new File(dstImgFolder);
//如果文件夹不存在则创建
if (!fileFolder.exists() && !fileFolder.isDirectory()) {
fileFolder.mkdir();
}
try {
// 将源文件转化到本地的
File file11 = HelloPdf.multipartFileToFile(dstImgFolder + "/", multipartFile);
String sourceFolder = dstImgFolder + "/" + uuId;
File oldFile = new File(sourceFolder);
// 这个是初始化 ,也写成功static 方法进行调用
PDFTransformImage pdfTransformImage = new PDFTransformImage();
// 返回来所有的图片
List<File> fileList = pdfTransformImage.pdfToImage(file11, dstImgFolder, 150, uuId);
if (fileList == null) {
return;
}
// 单个图片时候处理
if (ObjectUtil.equal("one", page)) {
// 所有的文件路径
List<String> list = new ArrayList<>();
for (File file : fileList) {
list.add(file.getAbsolutePath());
System.out.println(file.getAbsoluteFile());
}
// 所有文件
String[] objects = list.toArray(new String[]{});
// 保存文件路径和文件名字
String saveFile = sourceFolder + DateUtil.newSimpleFormat(DatePattern.PURE_DATETIME_PATTERN) + ".png";
// 将多个文件转换为一张图片
Image.merge(objects, "png", saveFile);
File srcFile = new File(saveFile);
// 最后 在打包 这个文件夹,然后下载
compress(zos, srcFile, srcFile.getName() + "/");
} else {
// 多个图片处理
File[] sourceFiles = oldFile.listFiles();
if (null == sourceFiles || sourceFiles.length < 1) {
System.out.println("待压缩的文件目录:" + "里面不存在文件,无需压缩.");
} else {
// 多个文件都压缩到文件
// 压缩文件为主
for (int i = 0; i < sourceFiles.length; i++) {
File srcFile = sourceFiles[i];
if (srcFile.isDirectory()) {
File[] imageSourceFiles = srcFile.listFiles();
if (null == imageSourceFiles || imageSourceFiles.length < 1) {
continue;
}
for (File imageFile : imageSourceFiles) {
compress(zos, imageFile, srcFile.getName() + "/");
}
} else {
compress(zos, srcFile, "");
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
try {
if (null != zos) {
zos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
// 最后删除本地的所有缓存文件
if (fileFolder.exists() && fileFolder.isDirectory()) {
deleteFolder(fileFolder);
}
}
}
pdf 转 图片这样方法
/**
* PDF文件转PNG图片,全部页数** @param PdfFilePath pdf完整路径
*
* @param dstImgFolder 图片存放的文件夹
* @param dpi dpi越大转换后越清晰,相对转换速度越慢* @return 返回转换后图片集合list
*/
public List<File> pdfToImage(File file, String dstImgFolder, int dpi, String uuId) {
// File file = new File(PdfFilePath);//定义集合保存返回图片数据
List<File> fileList = new ArrayList<File>();
PDDocument pdDocument;
try {
// String imagePDFName = file.getName().substring(0, "0"); // 获取图片文件名
String imgFolderPath = null;
if (dstImgFolder.equals("")) {
imgFolderPath = dstImgFolder + File.separator + uuId;// 获取图片存放的文件夹路径
} else {
imgFolderPath = dstImgFolder + File.separator + uuId;
}
if (createDirectory(imgFolderPath)) {
pdDocument = PDDocument.load(file);
PDFRenderer renderer = new PDFRenderer(pdDocument);
/* dpi越大转换后越清晰,相对转换速度越慢 */
PdfReader reader = new PdfReader(file.getAbsolutePath());
System.out.println("pdf总共多少页-----" + reader.getNumberOfPages());
StringBuilder imgFilePath = null;
for (int i = 0; i < reader.getNumberOfPages(); i++) {
String imgFilePathPrefix = imgFolderPath + File.separator + file.getName();
System.out.println("imgFilePathPrefix=====" + imgFilePathPrefix);
imgFilePath = new StringBuilder();
imgFilePath.append(imgFilePathPrefix);
imgFilePath.append("-");
imgFilePath.append(i);
imgFilePath.append(".jpg");
File dstFile = new File(imgFilePath.toString());
BufferedImage image = renderer.renderImageWithDPI(i, dpi);
ImageIO.write(image, "png", dstFile);
fileList.add(dstFile);
}
System.out.println("PDF文档转PNG图片成功!");
return fileList;
} else {
System.out.println("PDF文档转PNG图片失败:" + "创建" + imgFolderPath + "失败");
return null;
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
多张图片合并一张图片
public static boolean merge(String[] imgs, String type, String mergePic) {
int dstHeight = 0;
int dstWidth = 0;
// 获取需要拼接的图片长度
int len = imgs.length;
// 判断长度是否大于0
if (len < 1) {
return false;
}
File[] file = new File[len];
BufferedImage[] images = new BufferedImage[len];
int[][] ImageArrays = new int[len][];
for (int i = 0; i < len; i++) {
try {
file[i] = new File(imgs[i]);
images[i] = ImageIO.read(file[i]);
} catch (Exception e) {
e.printStackTrace();
return false;
}
int width = images[i].getWidth();
int height = images[i].getHeight();
// 从图片中读取RGB 像素
ImageArrays[i] = new int[width * height];
ImageArrays[i] = images[i].getRGB(0, 0, width, height, ImageArrays[i], 0, width);
// 计算合并的宽度和高度
dstWidth = dstWidth > width ? dstWidth : width;
dstHeight += height;
}
// 合成图片像素
System.out.println("宽度:" + dstWidth);
System.out.println("高度:" + dstHeight);
if (dstHeight < 1) {
System.out.println("dstHeight < 1");
return false;
}
// 生成新图片
try {
BufferedImage imageNew = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_ARGB);
// int width_i = 0;
int height_i = 0;
for (int i = 0; i < images.length; i++) {
int width = images[i].getWidth();
int height = images[i].getHeight();
imageNew.setRGB(0, height_i, width, height, ImageArrays[i], 0, width);
height_i += height;
}
File outFile = new File(mergePic);
// 写图片,输出到硬盘
ImageIO.write(imageNew, type, outFile);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}