diff --git a/compressed.jpg b/compressed.jpg new file mode 100644 index 0000000..e08ca9c Binary files /dev/null and b/compressed.jpg differ diff --git a/src/main/java/com/example/sso/controller/TuiZuController.java b/src/main/java/com/example/sso/controller/TuiZuController.java new file mode 100644 index 0000000..5d97663 --- /dev/null +++ b/src/main/java/com/example/sso/controller/TuiZuController.java @@ -0,0 +1,131 @@ +package com.example.sso.controller; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.example.sso.dao.Photo; +import com.example.sso.dao.ThumbnailCompressor; +import com.example.sso.test.O; +import com.example.sso.util.APIUtils; +import com.example.sso.util.TimeUtil; +import com.example.sso.util.TimeUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; + +@Async +@RestController +@Slf4j +public class TuiZuController { + + @PostMapping("/tz") + public void yuezu(@RequestBody JSONObject data) throws IOException { + + log.info("退租数据" + data.toJSONString()); + + JSONObject object = data.getJSONObject("data"); + String id = object.getString("_id"); + String car = object.getString("car"); + String sj = object.getString("sj"); + String timss = TimeUtil.timss(sj); + Integer gl = object.getInteger("gl"); + Integer dl = object.getInteger("dl"); + JSONArray mx = object.getJSONArray("mx"); + JSONArray yz = object.getJSONArray("yz"); + JSONArray cj = object.getJSONArray("cj"); + + String ww = object.getString("ww"); + + String wws = "姓名/联营方公司: " + ww; + String cars = "车牌号码:" + car; + String gls = "车辆公里数(KM): " + gl.toString(); + String dls = "车辆剩余电量(KM): " + dl.toString(); + String sjs = "验车时间:" + timss; + Photo.startPDF("/home/java/dpapp8090/pdf/" + id + ".pdf"); + Photo.TextAlignment("交车定损单"); + Photo.appendTextSection("\n"); + Photo.appendTextSection("驾驶员信息"); + Photo.appendTextSection("\n"); + Photo.appendTextSection(wws); + Photo.appendTextSection("\n"); + Photo.appendTextSection("\n"); + Photo.appendTextSection("\n"); + Photo.appendTextSection("车辆信息"); + Photo.appendTextSection("\n"); + Photo.appendTextSection(cars); + Photo.appendTextSection(gls); + Photo.appendTextSection(dls); + Photo.appendTextSection(sjs); + Photo.appendTextSection("\n"); + Photo.appendTextSection("\n"); + Photo.appendTextSection("\n"); + Photo.appendTextSection("车辆整体照片"); + + + for (Object yzs : yz) { + JSONObject jsonObject = (JSONObject) yzs; + String url = jsonObject.getString("url"); + String hkfile = APIUtils.hkfile(url); + ThumbnailCompressor.compressWithThumbnailator(hkfile, hkfile); + Photo.appendImageSection(hkfile); + + } + + Photo.appendTextSection("车架号照片"); + + for (Object yzs : cj) { + JSONObject jsonObject = (JSONObject) yzs; + String url = jsonObject.getString("url"); + String hkfile = APIUtils.hkfile(url); + ThumbnailCompressor.compressWithThumbnailator(hkfile, hkfile); + Photo.appendImageSection(hkfile); + + } + + Photo.appendTextSection("\n"); + Photo.appendTextSection("\n"); + Photo.appendTextSection("\n"); + + + + for (Object o : mx) { + + JSONObject test = (JSONObject) o; + String xiang = test.getString("xiang"); + + String xiangs = "验车受损项:" + xiang; + + + + Photo.appendTextSection(xiangs); + + JSONArray tp = test.getJSONArray("tp"); + if (tp != null && tp.size() != 0) { + for (Object o1 : tp) { + JSONObject tests = (JSONObject) o1; + String url = tests.getString("url"); + String hkfile = APIUtils.hkfile(url); + ThumbnailCompressor.compressWithThumbnailator(hkfile, hkfile); + Photo.appendTextSection("车损详情图片:"); + Photo.appendTextSection("\n"); + Photo.appendImageSection(hkfile); + } + } + Photo.appendTextSection("\n"); + + + + + } + + + + + + Photo.closePDF(); + + } +} diff --git a/src/main/java/com/example/sso/dao/Photo.java b/src/main/java/com/example/sso/dao/Photo.java new file mode 100644 index 0000000..23d2e64 --- /dev/null +++ b/src/main/java/com/example/sso/dao/Photo.java @@ -0,0 +1,274 @@ +package com.example.sso.dao; + +import com.itextpdf.io.image.ImageData; +import com.itextpdf.io.image.ImageDataFactory; +import com.itextpdf.kernel.font.PdfFont; +import com.itextpdf.kernel.font.PdfFontFactory; +import com.itextpdf.kernel.geom.PageSize; +import com.itextpdf.kernel.pdf.PdfDocument; +import com.itextpdf.kernel.pdf.PdfWriter; +import com.itextpdf.layout.Document; +import com.itextpdf.layout.element.Image; +import com.itextpdf.layout.element.Paragraph; +import com.itextpdf.layout.properties.TextAlignment; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +public class Photo { + + private static PdfDocument pdfDoc = null; + private static Document document = null; + private static String currentPdfPath = null; + + /** + * 开始创建PDF + */ + public static void startPDF(String pdfPath) throws IOException { + if (pdfDoc != null) { + closePDF(); + } + + /* currentPdfPath = pdfPath; + PdfWriter writer = new PdfWriter(pdfPath); + pdfDoc = new PdfDocument(writer); + // document = new Document(pdfDoc); + // 创建文档时设置0边距 + document = new Document(pdfDoc, PageSize.A4, false); + + // 设置页边距为0 + document.setMargins(0, 0, 0, 0); + // 或者使用具体的值 + // document.setMargins(0f, 0f, 0f, 0f); + + // 移除默认的页眉页脚 + pdfDoc.getDefaultPageSize();*/ + + + + currentPdfPath = pdfPath; + PdfWriter writer = new PdfWriter(pdfPath); + pdfDoc = new PdfDocument(writer); + + // A4纸的标准宽度是595点(约210mm),高度自定义 + // PageSize.A4.getWidth() 获取A4宽度 + PageSize customPageSize = new PageSize(PageSize.A4.getWidth(), 842*20); + + document = new Document(pdfDoc, customPageSize, false); + document.setMargins(0, 0, 0, 0); + + + + System.out.println("开始创建PDF: " + pdfPath); + } + + /** + * 添加图片章节 + */ + public static void appendImageSection(String imagePath) throws IOException { + if (document == null) { + throw new IllegalStateException("请先调用 startPDF() 方法"); + } + + // 添加章节标题 +// document.add(new Paragraph("图片部分") +// .setFontSize(20) +// .setBold() +// .setMarginTop(20)); + + // 添加图片 + if (imagePath != null && new File(imagePath).exists()) { + ImageData imageData = ImageDataFactory.create(imagePath); + Image image = new Image(imageData); + + // image.setAutoScale(true); + image.setHorizontalAlignment(com.itextpdf.layout.properties.HorizontalAlignment.CENTER); + image.setMarginTop(5); + image.setMarginBottom(5); + image.setHeight(200); + image.setWidth(200); + + document.add(image); +// document.add(new Paragraph("图片说明") +// .setFontSize(10) +// .setItalic() +// .setTextAlignment(com.itextpdf.layout.properties.TextAlignment.CENTER)); + } + + System.out.println("已添加图片章节"); + } + + /** + * 添加文本章节 + */ + public static void appendTextSection(String text) throws IOException { + if (document == null) { + throw new IllegalStateException("请先调用 startPDF() 方法"); + + + } + + PdfFont chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H"); + + // 添加章节标题 + document.add(new Paragraph(text) + .setFont(chineseFont) + .setFontSize(20) + .setBold() + .setMarginTop(20)); + + /* // 添加文本 + if (text != null && !text.trim().isEmpty()) { + String[] paragraphs = text.split("\n"); + for (String para : paragraphs) { + document.add(new Paragraph(para) + .setFontSize(12) + .setMarginBottom(10)); + } + }*/ + + System.out.println("已添加文本章节"); + } + + public static void TextAlignment(String text) throws IOException { + if (document == null) { + throw new IllegalStateException("请先调用 startPDF() 方法"); + + + } + + PdfFont chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H"); + + // 创建段落并设置居中对齐 + Paragraph paragraph = new Paragraph(text) + .setFont(chineseFont) + .setFontSize(20) + .setBold() + .setMarginTop(20) + .setTextAlignment(TextAlignment.CENTER); // 添加这行实现居中 + + document.add(paragraph); + System.out.println("已添加文本章节"); + } + + + public static void appendTextSections(String text) throws IOException { + if (document == null) { + throw new IllegalStateException("请先调用 startPDF() 方法"); + + + } + + PdfFont chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H"); + + // 添加章节标题 + // 设置绝对位置在页面底部 + Paragraph paragraph = new Paragraph(text); + float pageHeight = PageSize.A4.getHeight(); // 842点 + float bottomMargin = 50; // 距离底部50点 + float leftMargin = 400; // 左边距 + + paragraph.setFixedPosition(leftMargin, bottomMargin, PageSize.A4.getWidth() - 40).setFont(chineseFont); + document.add(paragraph); + + /* // 添加文本 + if (text != null && !text.trim().isEmpty()) { + String[] paragraphs = text.split("\n"); + for (String para : paragraphs) { + document.add(new Paragraph(para) + .setFontSize(12) + .setMarginBottom(10)); + } + }*/ + + System.out.println("已添加文本章节"); + } + + /** + * 添加分页符 + */ + public static void addPageBreak() { + if (document != null) { + document.add(new com.itextpdf.layout.element.AreaBreak()); + System.out.println("已添加分页符"); + } + } + + /** + * 关闭并保存PDF + */ + public static void closePDF() { + if (document != null) { + document.close(); + document = null; + } + if (pdfDoc != null) { + pdfDoc.close(); + pdfDoc = null; + } + + System.out.println("PDF已保存: " + currentPdfPath); + currentPdfPath = null; + } + + /** + * 快速使用示例 + */ + public static void createPDFWithMultipleSections(String pdfPath) throws IOException { + startPDF(pdfPath); + + // 添加各种内容 + appendTextSection("这是文档的第一部分\n包含一些介绍性的文字"); + + + appendImageSection("image1.jpg"); + appendTextSection("这是图片1的描述文字"); + + appendImageSection("image2.png"); + appendTextSection("这是图片2的描述文字"); + + // 关闭并保存 + closePDF(); + } + + + + + public static void createSimpleChinesePDF() throws IOException { + // 1. 创建PDF + PdfWriter writer = new PdfWriter("D:\\下载模板\\a.pdf"); + PdfDocument pdfDoc = new PdfDocument(writer); + Document document = new Document(pdfDoc); + + // 2. 加载中文字体(必须要有font-asian依赖) + PdfFont chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H"); + + // 3. 添加中文内容 + Paragraph title = new Paragraph("中文标题") + .setFont(chineseFont) + .setFontSize(20) + .setBold(); + document.add(title); + + Paragraph content = new Paragraph("这是中文内容,可以正常显示。") + .setFont(chineseFont) + .setFontSize(12); + document.add(content); + + // 4. 关闭文档 + document.close(); + + System.out.println("PDF创建完成"); + } + + public static void main(String[] args) { + try { + createSimpleChinesePDF(); + } catch (IOException e) { + System.out.println("错误: " + e.getMessage()); + System.out.println("请确保添加了 font-asian 依赖"); + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/example/sso/dao/ThumbnailCompressor.java b/src/main/java/com/example/sso/dao/ThumbnailCompressor.java new file mode 100644 index 0000000..2707b64 --- /dev/null +++ b/src/main/java/com/example/sso/dao/ThumbnailCompressor.java @@ -0,0 +1,114 @@ +package com.example.sso.dao; + +import net.coobird.thumbnailator.Thumbnails; +import net.coobird.thumbnailator.geometry.Positions; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class ThumbnailCompressor { + + private static final long MAX_SIZE = 300 * 1024; // 500KB + + /** + * 使用Thumbnailator压缩图片 + */ + public static long compressWithThumbnailator(String inputPath, String outputPath) throws IOException { + File inputFile = new File(inputPath); + long fileSize = inputFile.length(); + + System.out.println("原始大小: " + formatFileSize(fileSize)); + + // 如果小于500KB,直接复制 + if (fileSize <= MAX_SIZE) { + Files.copy(inputFile.toPath(), Paths.get(outputPath)); + return fileSize; + } + + // 获取图片尺寸 + BufferedImage originalImage = ImageIO.read(inputFile); + int width = originalImage.getWidth(); + int height = originalImage.getHeight(); + + // 计算缩放比例 + float scale = 1.0f; + if (width > 1920 || height > 1080) { + float widthRatio = 1920f / width; + float heightRatio = 1080f / height; + scale = Math.min(widthRatio, heightRatio); + } + + // 逐步压缩 + float quality = 0.9f; + long compressedSize = Long.MAX_VALUE; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + while (quality > 0.1f && compressedSize > MAX_SIZE) { + baos.reset(); + + Thumbnails.of(inputFile) + .scale(scale) + .outputQuality(quality) + .outputFormat("jpg") + .toOutputStream(baos); + + compressedSize = baos.size(); + System.out.println("质量: " + quality + ", 大小: " + formatFileSize(compressedSize)); + + quality -= 0.1f; + } + + // 保存文件 + try (FileOutputStream fos = new FileOutputStream(outputPath)) { + fos.write(baos.toByteArray()); + } + + return compressedSize; + } + + /** + * 批量压缩 + */ + public static void batchCompress(String inputDir, String outputDir, long maxSize) throws IOException { + File dir = new File(inputDir); + File[] imageFiles = dir.listFiles((d, name) -> + name.toLowerCase().endsWith(".jpg") || + name.toLowerCase().endsWith(".jpeg") || + name.toLowerCase().endsWith(".png") || + name.toLowerCase().endsWith(".bmp") + ); + + if (imageFiles == null) return; + + for (File imageFile : imageFiles) { + String outputPath = outputDir + File.separator + "compressed_" + imageFile.getName(); + long compressedSize = compressWithThumbnailator(imageFile.getPath(), outputPath); + + System.out.println(imageFile.getName() + + " 压缩后: " + formatFileSize(compressedSize)); + } + } + + private static String formatFileSize(long size) { + if (size < 1024) return size + " B"; + if (size < 1024 * 1024) return String.format("%.2f KB", size / 1024.0); + if (size < 1024 * 1024 * 1024) return String.format("%.2f MB", size / (1024.0 * 1024.0)); + return String.format("%.2f GB", size / (1024.0 * 1024.0 * 1024.0)); + } + + public static void main(String[] args) { + try { + // 压缩单个图片 + long size = compressWithThumbnailator("D:\\下载模板\\微信图片_20251224111834_4_27.jpg", "D:\\下载模板\\微信图片_20251224111834_4_27.jpg"); + System.out.println("最终大小: " + formatFileSize(size)); + + // 批量压缩 + // batchCompress("input_images", "output_images", 500 * 1024); + + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file