diff --git a/src/main/java/com/point/strategy/archiveFile/controller/ArchiveFileController.java b/src/main/java/com/point/strategy/archiveFile/controller/ArchiveFileController.java index ede5c02..40679f5 100644 --- a/src/main/java/com/point/strategy/archiveFile/controller/ArchiveFileController.java +++ b/src/main/java/com/point/strategy/archiveFile/controller/ArchiveFileController.java @@ -5,6 +5,7 @@ import com.itextpdf.text.pdf.PdfDocument; import com.itextpdf.text.pdf.PdfReader; import com.point.strategy.archiveFile.service.ArchiveFileService; import com.point.strategy.common.*; +import com.point.strategy.common.ImageToPdfConverter; import com.point.strategy.user.bean.User; import com.point.strategy.user.service.UserService; import io.swagger.annotations.Api; @@ -170,36 +171,37 @@ public class ArchiveFileController { }else { // 大文件直接返回,不加水印 if (isLargeFile) { - String contentType = "image/jpeg"; - if (split[split.length-1].equalsIgnoreCase("png")) { - contentType = "image/png"; - } - response.setContentType(contentType + ";charset=UTF-8"); - - try (InputStream in = new FileInputStream(file); - ServletOutputStream out = response.getOutputStream()) { + // 将图片转换为PDF + try (InputStream in = new FileInputStream(file)) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ImageToPdfConverter.convertImageToPdf(in, outputStream); - byte[] buffer = new byte[8192]; - int bytesRead; - while ((bytesRead = in.read(buffer)) != -1) { - out.write(buffer, 0, bytesRead); + response.setContentType("application/pdf;charset=UTF-8"); + try (ServletOutputStream out = response.getOutputStream()) { + out.write(outputStream.toByteArray()); + out.flush(); } - out.flush(); + } catch (Exception e) { + log.error("图片转PDF失败: {}", e.getMessage(), e); + throw new IOException("图片转PDF失败: " + e.getMessage(), e); } } else { - // 小文件加水印处理 - ByteArrayOutputStream outputStream = addWatermarkByFileIo(downLoadPath, user.getUsername()); - // 根据文件类型设置正确的Content-Type - String contentType = "image/jpeg"; - if (split[split.length-1].equalsIgnoreCase("png")) { - contentType = "image/png"; - } - response.setContentType(contentType + ";charset=UTF-8"); - try (ServletOutputStream out = response.getOutputStream()) { - out.write(outputStream.toByteArray()); - out.flush(); + // 小文件加水印处理,然后转换为PDF + ByteArrayOutputStream imageStream = addWatermarkByFileIo(downLoadPath, user.getUsername()); + try (InputStream in = new ByteArrayInputStream(imageStream.toByteArray())) { + ByteArrayOutputStream pdfStream = new ByteArrayOutputStream(); + ImageToPdfConverter.convertImageToPdf(in, pdfStream); + + response.setContentType("application/pdf;charset=UTF-8"); + try (ServletOutputStream out = response.getOutputStream()) { + out.write(pdfStream.toByteArray()); + out.flush(); + } + } catch (Exception e) { + log.error("图片转PDF失败: {}", e.getMessage(), e); + throw new IOException("图片转PDF失败: " + e.getMessage(), e); } finally { - outputStream.close(); + imageStream.close(); } } } diff --git a/src/main/java/com/point/strategy/common/ImageToPdfConverter.java b/src/main/java/com/point/strategy/common/ImageToPdfConverter.java new file mode 100644 index 0000000..0979ff6 --- /dev/null +++ b/src/main/java/com/point/strategy/common/ImageToPdfConverter.java @@ -0,0 +1,122 @@ +package com.point.strategy.common; + +import com.drew.imaging.ImageMetadataReader; +import com.drew.metadata.Directory; +import com.drew.metadata.Metadata; +import com.drew.metadata.exif.ExifDirectoryBase; +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.Image; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.PdfWriter; +import lombok.extern.slf4j.Slf4j; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * 图片转PDF工具类 + * 支持将jpg、png等图片格式转换为PDF + */ +@Slf4j +public class ImageToPdfConverter { + + /** + * 将图片输入流转换为PDF输出流 + * + * @param imageInputStream 图片输入流 + * @param pdfOutputStream PDF输出流 + * @throws IOException IO异常 + * @throws DocumentException 文档异常 + */ + public static void convertImageToPdf(InputStream imageInputStream, ByteArrayOutputStream pdfOutputStream) + throws IOException, DocumentException { + try { + // 创建临时文件来获取EXIF信息(因为ImageMetadataReader需要File对象) + // 由于我们只有InputStream,需要先创建临时图片文件 + java.io.File tempImageFile = java.io.File.createTempFile("temp_image_", ".jpg"); + tempImageFile.deleteOnExit(); + + // 将输入流写入临时文件 + try (java.io.FileOutputStream fos = new java.io.FileOutputStream(tempImageFile)) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = imageInputStream.read(buffer)) != -1) { + fos.write(buffer, 0, bytesRead); + } + } + + // 读取图片并获取EXIF方向信息 + Image image = Image.getInstance(tempImageFile.getAbsolutePath()); + int orientation = getExifOrientation(tempImageFile); + + // 根据EXIF方向调整图片 + adjustImageOrientation(image, orientation); + + // 创建PDF文档,使用图片的原始尺寸 + Document document = new Document(new Rectangle(image.getWidth(), image.getHeight())); + PdfWriter.getInstance(document, pdfOutputStream); + document.open(); + + // 添加图片到PDF + document.add(image); + document.close(); + + // 删除临时文件 + tempImageFile.delete(); + + } catch (Exception e) { + log.error("图片转PDF失败: {}", e.getMessage(), e); + throw e; + } + } + + /** + * 获取图片的EXIF方向信息 + * + * @param imageFile 图片文件 + * @return 方向值 (1=正常, 3=180度, 6=90度, 8=270度) + */ + private static int getExifOrientation(java.io.File imageFile) { + try { + Metadata metadata = ImageMetadataReader.readMetadata(imageFile); + + // 遍历元数据目录,查找 EXIF 方向标签 + for (Directory directory : metadata.getDirectories()) { + if (directory.containsTag(ExifDirectoryBase.TAG_ORIENTATION)) { + return directory.getInt(ExifDirectoryBase.TAG_ORIENTATION); + } + } + } catch (Exception e) { + log.warn("读取EXIF方向失败: {}", e.getMessage()); + } + return 1; // 默认方向:正常 + } + + /** + * 根据EXIF方向调整图片 + * + * @param image 图片对象 + * @param orientation 方向值 + * @throws DocumentException 文档异常 + */ + private static void adjustImageOrientation(Image image, int orientation) throws DocumentException { + switch (orientation) { + case 1: // 正常 + break; + case 3: // 旋转180度 + image.setRotationDegrees(180); + break; + case 6: // 顺时针旋转90度 + image.setRotationDegrees(90); + break; + case 8: // 逆时针旋转90度 + image.setRotationDegrees(270); + break; + default: + // 其他情况保持原样 + break; + } + } +} \ No newline at end of file