瀏覽代碼

组成相册 保证相片是连续的

cr 2 周之前
父節點
當前提交
f6c5eee58d

+ 3 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/ImageClassificationFileClient.java

@@ -1,6 +1,7 @@
 package org.springblade.business.feign;
 
 import org.springblade.business.dto.ImageClassificationFileDTO;
+import org.springblade.business.entity.ImageClassificationFile;
 import org.springblade.common.constant.BusinessConstant;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -25,4 +26,6 @@ public interface ImageClassificationFileClient {
     @PostMapping(API_PREFIX + "/getImageClassificationFileListByContractId")
     List<ImageClassificationFileDTO> getImageClassificationFileListByContractId(@RequestBody Long contractId);
 
+    @PostMapping(API_PREFIX + "/getImageClassificationFileById")
+    ImageClassificationFile getImageClassificationFileById(@RequestBody Long id);
 }

+ 1 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/AlbumDTO.java

@@ -33,7 +33,7 @@ import java.util.List;
 public class AlbumDTO extends Album {
 	private static final long serialVersionUID = 1L;
 
-	private List<String> margePdfUrls;
+	private List<AlbumDTO1> margePdfUrls;
 
 	private String dateValue;
 

+ 9 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/AlbumDTO1.java

@@ -0,0 +1,9 @@
+package org.springblade.manager.dto;
+
+import lombok.Data;
+
+@Data
+public class AlbumDTO1 {
+    private Long id;
+    private String imageUrl;
+}

+ 8 - 0
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ImageClassificationFileClientImpl.java

@@ -2,8 +2,10 @@ package org.springblade.business.feignClient;
 
 import lombok.AllArgsConstructor;
 import org.springblade.business.dto.ImageClassificationFileDTO;
+import org.springblade.business.entity.ImageClassificationFile;
 import org.springblade.business.feign.ImageClassificationFileClient;
 import org.springblade.business.mapper.ImageClassificationFileMapper;
+import org.springblade.business.service.IImageClassificationFileService;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
@@ -13,10 +15,16 @@ import java.util.List;
 public class ImageClassificationFileClientImpl implements ImageClassificationFileClient {
 
     private final ImageClassificationFileMapper imageClassificationFileMapper;
+    private final IImageClassificationFileService imageClassificationFileService;
 
     @Override
     public List<ImageClassificationFileDTO> getImageClassificationFileListByContractId(Long contractId) {
         return imageClassificationFileMapper.getImageClassificationFileListByContractId(contractId);
     }
 
+    @Override
+    public ImageClassificationFile getImageClassificationFileById(Long id) {
+        return imageClassificationFileService.getById(id);
+    }
+
 }

+ 180 - 11
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/AlbumController.java

@@ -16,7 +16,11 @@
  */
 package org.springblade.manager.controller;
 
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.nacos.common.utils.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
@@ -24,8 +28,15 @@ import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
 import javax.validation.Valid;
 
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.util.IOUtils;
+import org.springblade.business.entity.ImageClassificationFile;
+import org.springblade.business.feign.ImageClassificationFileClient;
 import org.springblade.common.constant.CommonConstant;
+import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.common.utils.SystemUtils;
+import org.springblade.common.vo.DataVO;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
@@ -33,10 +44,19 @@ import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.IoUtil;
+import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.manager.dto.AlbumDTO;
+import org.springblade.manager.dto.AlbumDTO1;
+import org.springblade.manager.entity.ExcelTab;
+import org.springblade.manager.feign.ExcelTabClient;
+import org.springblade.manager.feign.ImageClassificationConfigClient;
 import org.springblade.manager.utils.FileUtils;
+import org.springblade.resource.feign.CommonFileClient;
 import org.springblade.resource.feign.NewIOSSClient;
+import org.springblade.resource.vo.NewBladeFile;
 import org.springblade.system.cache.ParamCache;
+import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -45,6 +65,16 @@ import org.springblade.manager.vo.AlbumVO;
 import org.springblade.manager.wrapper.AlbumWrapper;
 import org.springblade.manager.service.IAlbumService;
 import org.springblade.core.boot.ctrl.BladeController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
 
 /**
  *  控制器
@@ -62,6 +92,12 @@ public class AlbumController extends BladeController {
 
 	private final NewIOSSClient newIOSSClient;
 
+	private final ExcelTabClient excelTabClient;
+
+	private final ImageClassificationFileClient imageClassificationFileClient;
+
+	private final CommonFileClient commonFileClient;
+
 	/**
 	 * 详情
 	 */
@@ -106,26 +142,159 @@ public class AlbumController extends BladeController {
 		if(albumDTO.getMargePdfUrls().isEmpty()){
 			throw new ServiceException("相册不能为空");
 		}
+		List<String>uris=new ArrayList<>();
+		HashMap<String, Long> map = new HashMap<>();
+		for (AlbumDTO1 margePdfUrl : albumDTO.getMargePdfUrls()) {
+			String imageUrl = margePdfUrl.getImageUrl();
+			String[] urlss = imageUrl.split(",");
+			for (String string : urlss) {
+				map.put(string,margePdfUrl.getId());
+				uris.add(string);
+			}
+		}
+		if(uris.isEmpty()){
+			throw new ServiceException("相册不能为空");
+		}
 		Album album=new Album();
 		BeanUtil.copy(albumDTO,album);
 		String dateValue = albumDTO.getDateValue();
 		String[] strings = dateValue.split("~");
 		album.setStartDate(strings[0]);
 		album.setEndDate(strings[1]);
-		if(albumDTO.getMargePdfUrls().size()>1){
-			String file_path = FileUtils.getSysLocalFileUrl();
-			Long id = SnowFlakeUtil.getId();
-			String mergeName=id+".pdf";
-			String mergeUrl = file_path + "/nodePDF/"+id+".pdf";;
-			FileUtils.mergePdfPublicMethods(albumDTO.getMargePdfUrls(), mergeUrl);
-			BladeFile bladeFile = this.newIOSSClient.uploadFile(mergeName, mergeUrl);
-			if (bladeFile != null && ObjectUtils.isNotEmpty(bladeFile.getLink())) {
-				album.setImagesPdf(bladeFile.getLink());
+		//获取固定表格
+		ExcelTab excelTab = this.excelTabClient.getById("1550363881879781377"); //影像资料模板
+		String file_path = null;
+		if (SystemUtils.isWindows()) {
+			file_path = "C:\\pdfFiles\\";
+			File file = new File(file_path);
+			if (!file.exists()) {
+				file.mkdirs();
+			}
+		}
+		if (SystemUtils.isLinux()) {
+			file_path = "/home/pdfFiles";
+			File file = new File(file_path);
+			if (!file.exists()) {
+				file.mkdirs();
 			}
-		}else {
-			album.setImagesPdf(albumDTO.getMargePdfUrls().get(0));
 		}
+		if (excelTab != null) {
+			//获取数据
+			try {
+					//需要删除的本地文件集合
+					List<String> removeList = new ArrayList<>();
+							//获取模板文件流
+							InputStream modInput = null;
+							FileInputStream excelFileInput = null;
+							FileOutputStream outputStream = null;
+							Workbook workbook = null;
 
+							List<String> pdfFileList = new ArrayList<>();
+							//两个图片一组
+							List<List<String>> groupUrls =  CommonUtil.getBatchSize(uris, 2);
+							for (List<String> urls : groupUrls) {
+								try {
+									//创建模板Workbook
+									modInput = CommonUtil.getOSSInputStream(excelTab.getFileUrl());
+									if (modInput != null) {
+										workbook = WorkbookFactory.create(modInput);
+										for (int i = 0, l = urls.size(); i < l; i++) {
+											try {
+												CreationHelper helper = workbook.getCreationHelper();
+												Sheet sheet = workbook.getSheetAt(0);
+												Drawing<?> drawing = sheet.createDrawingPatriarch();
+												ClientAnchor anchor = helper.createClientAnchor();
+												Long id = map.get(urls.get(i));
+								                ImageClassificationFile file=imageClassificationFileClient.getImageClassificationFileById(id);
+												//获取文件流
+												byte[] bytes = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(urls.get(i)));
+												if (bytes[0] == 82 && bytes[1] == 73 && bytes[2] == 70){
+													bytes = CommonUtil.webpToPngBytes(CommonUtil.getOSSInputStream(urls.get(i)));
+												}
+												//压缩文件大小
+												byte[] byteNew = FileUtils.compressImage(bytes);
+												//创建图片
+												Picture picture = drawing.createPicture(anchor, workbook.addPicture(byteNew, Workbook.PICTURE_TYPE_PNG));
+												picture.resize();
+
+												//图片定位
+												FileUtils.imageOrientation(sheet, anchor, i == 1 ? new DataVO(1, 8) : new DataVO(0, 2));
+
+												//定位其它信息
+												//文字说明
+												sheet.getRow(i == 0 ? 0 : 6).getCell(i == 0 ? 3 : 0).setCellValue("文字说明:\n" + "  " + (ObjectUtil.isNotEmpty(file.getTextContent()) ? file.getTextContent() : ""));
+												//照片号
+												sheet.getRow(i == 0 ? 1 : 7).getCell(i == 0 ? 3 : 0).setCellValue("照片号:\n" + "  " + (ObjectUtil.isNotEmpty(file.getPhotoCode()) ? file.getPhotoCode() : ""));
+												//底片号
+												sheet.getRow(i == 0 ? 2 : 8).getCell(i == 0 ? 3 : 0).setCellValue("底片号:\n" + "  " + (ObjectUtil.isNotEmpty(file.getFilmCode()) ? file.getFilmCode() : ""));
+												//题名
+												sheet.getRow(i == 0 ? 3 : 9).getCell(i == 0 ? 0 : 2).setCellValue("题名:\n" + "  " + (ObjectUtil.isNotEmpty(file.getTitle()) ? file.getTitle() : ""));
+												//参见号
+												sheet.getRow(i == 0 ? 3 : 9).getCell(i == 0 ? 2 : 0).setCellValue("参见号:\n" + "  " + (ObjectUtil.isNotEmpty(file.getSeeAlsoCode()) ? file.getSeeAlsoCode() : ""));
+												//拍摄时间
+												sheet.getRow(i == 0 ? 4 : 10).getCell(i == 0 ? 2 : 0).setCellValue("拍摄时间:\n" + "  " + (ObjectUtil.isNotEmpty(DateUtil.format(file.getShootingTime(), "yyyy-MM-dd")) ? DateUtil.format(file.getShootingTime(), "yyyy-MM-dd") : ""));
+												//拍摄者
+												sheet.getRow(i == 0 ? 5 : 11).getCell(i == 0 ? 2 : 0).setCellValue("拍摄者:\n" + "  " + (ObjectUtil.isNotEmpty(file.getShootingUser()) ? file.getShootingUser() : ""));
+
+											} catch (Exception e) {
+												e.printStackTrace();
+											}
+										}
+
+										String locationFile = file_path + SnowFlakeUtil.getId() + ".xlsx";
+										outputStream = new FileOutputStream(locationFile);
+										//记录文件删除
+										removeList.add(locationFile);
+										//生成一份新的excel
+										workbook.write(outputStream);
+										//将excel转PDF
+										File excelFile = new File(locationFile);
+										excelFileInput = new FileInputStream(excelFile);
+										MultipartFile files = new MockMultipartFile("file", excelFile.getName(), "text/plain", IOUtils.toByteArray(excelFileInput));
+										NewBladeFile bladeFile = this.commonFileClient.excelToPdf(files);
+										if (bladeFile != null) {
+											pdfFileList.add(bladeFile.getPdfUrl());
+										}
+									}
+								} catch (Exception e) {
+									e.printStackTrace();
+								} finally {
+									if (outputStream != null) {
+										IoUtil.closeQuietly(outputStream);
+									}
+									if (modInput != null) {
+										IoUtil.closeQuietly(modInput);
+									}
+									if (excelFileInput != null) {
+										IoUtil.closeQuietly(excelFileInput);
+									}
+									if (workbook != null) {
+										IoUtil.closeQuietly(workbook);
+									}
+								}
+							}
+
+							//合并pdf并上传
+							String mergeName = SnowFlakeUtil.getId() + ".pdf";
+							String mergeUrl = file_path + mergeName;
+							FileUtils.mergePdfPublicMethods(pdfFileList, mergeUrl);
+							//记录文件删除
+							removeList.add(mergeUrl);
+							//上传
+							BladeFile bladeFile = this.newIOSSClient.uploadFile(mergeName, mergeUrl);
+							if (bladeFile != null) {
+								album.setImagesPdf(bladeFile.getLink());
+							}
+
+					if (removeList.size() > 0) {
+						//删除本地文件
+						CommonUtil.removeFile(removeList);
+					}
+
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
 		return R.status(albumService.save(album));
 	}
 

+ 88 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/FileUtils.java

@@ -3,6 +3,11 @@ package org.springblade.manager.utils;
 import com.aspose.cells.PdfSaveOptions;
 import com.aspose.cells.SaveFormat;
 import com.aspose.cells.Workbook;
+import com.drew.imaging.ImageMetadataReader;
+import com.drew.imaging.ImageProcessingException;
+import com.drew.metadata.Metadata;
+import com.drew.metadata.MetadataException;
+import com.drew.metadata.exif.ExifIFD0Directory;
 import com.itextpdf.io.image.ImageType;
 import com.itextpdf.text.Document;
 import com.itextpdf.text.pdf.PdfCopy;
@@ -37,9 +42,14 @@ import org.springblade.core.tool.utils.ResourceUtil;
 import org.springblade.system.cache.ParamCache;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.imageio.IIOImage;
 import javax.imageio.ImageIO;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
 import javax.servlet.http.HttpServletResponse;
 import java.awt.*;
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
 import java.awt.image.BufferedImage;
 import java.io.*;
 import java.net.URLEncoder;
@@ -123,6 +133,84 @@ public class FileUtils {
         }
     }
 
+
+    public static byte[] compressImage(byte[] imageData) throws IOException, ImageProcessingException, MetadataException {
+        // 读取原始图像(处理旋转问题)
+        Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
+        if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
+            ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
+            if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
+                // 获取 Orientation 标签的值
+                int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
+                // 需要旋转图片
+                BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(imageData));
+                AffineTransform transform = new AffineTransform();
+                if (orientation == 6) {
+                    transform.rotate(Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
+                } else if (orientation == 8) {
+                    transform.rotate(-Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
+                }
+                AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
+                originalImage = op.filter(originalImage, null);
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                ImageIO.write(originalImage, "jpg", baos);
+                imageData = baos.toByteArray();
+            }
+        }
+        // 缩放图像
+        String formatName = "JPEG";
+        ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
+        BufferedImage originalImage = ImageIO.read(bais);
+        long sizeLimit = 366912; //358KB
+        int width = 768;
+        int height = 1024;
+        Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
+        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+        resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
+
+        // 压缩图像
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ImageIO.write(resizedImage, formatName, baos);
+
+        if (baos.size() <= sizeLimit) {
+            // 图片大小已经小于等于目标大小,直接返回原始数据
+            return baos.toByteArray();
+        }
+
+        float quality = 0.9f; // 初始化压缩质量
+        int retries = 10; // 最多尝试 10 次
+
+        while (baos.size() > sizeLimit && retries > 0) {
+            // 压缩图像并重新计算压缩质量
+            byte[] data = baos.toByteArray();
+            bais = new ByteArrayInputStream(data);
+            BufferedImage compressedImage = ImageIO.read(bais);
+            baos.reset();
+
+            ImageWriter writer = null;
+            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
+            if (writers.hasNext()) {
+                writer = writers.next();
+            } else {
+                throw new IllegalArgumentException("Unsupported image format: " + formatName);
+            }
+
+            ImageWriteParam writeParam = writer.getDefaultWriteParam();
+            writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+            writeParam.setCompressionQuality(quality);
+
+            writer.setOutput(ImageIO.createImageOutputStream(baos));
+            writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
+            writer.dispose();
+
+            float ratio = sizeLimit * 1.0f / baos.size();
+            quality *= Math.sqrt(ratio);
+            retries--;
+        }
+
+        return baos.toByteArray();
+    }
+
     /**
      * 图片定位
      */