|
|
@@ -3,6 +3,7 @@ package com.jzg.quotation.huatai.crawler.util;
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.core.io.ByteArrayResource;
|
|
|
import org.springframework.core.io.FileSystemResource;
|
|
|
import org.springframework.http.*;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
@@ -70,74 +71,75 @@ public class UploadUtil {
|
|
|
|
|
|
/**
|
|
|
* 压缩图片并返回 Base64(对应 Python 中的 ys_photo)
|
|
|
+ * 【已改造】无文件创建、纯内存流、保留压缩、返回新base64
|
|
|
*/
|
|
|
public String ysPhoto(String base64Image) throws Exception {
|
|
|
+ // 1. Base64 解码成字节数组
|
|
|
byte[] imageBytes = Base64.getDecoder().decode(base64Image);
|
|
|
- File tempDir = new File(imagesPath + "huatai/");
|
|
|
- if (!tempDir.exists()) {
|
|
|
- tempDir.mkdirs();
|
|
|
- }
|
|
|
- File zzFile = File.createTempFile(imagesPath + "huatai/" + "upload_temp_zz", ".jpg", tempDir);
|
|
|
- try (FileOutputStream fos = new FileOutputStream(zzFile)) {
|
|
|
- fos.write(imageBytes);
|
|
|
- }
|
|
|
|
|
|
- BufferedImage img = ImageIO.read(zzFile);
|
|
|
+ // 2. 从内存流直接读取图片(不创建文件)
|
|
|
+ ByteArrayInputStream bais = new ByteArrayInputStream(imageBytes);
|
|
|
+ BufferedImage img = ImageIO.read(bais);
|
|
|
+ bais.close();
|
|
|
+
|
|
|
if (img == null) {
|
|
|
- throw new IOException("无法读取图片: " + zzFile.getAbsolutePath());
|
|
|
+ throw new IOException("无法读取图片:字节流解析失败");
|
|
|
}
|
|
|
+
|
|
|
+ // 3. 转 RGB 格式(去掉透明通道,原逻辑保留)
|
|
|
BufferedImage rgbImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
|
|
|
rgbImg.createGraphics().drawImage(img, 0, 0, null);
|
|
|
|
|
|
- File sbFile = File.createTempFile(imagesPath + "huatai/" + "upload_temp_sb", ".jpg", tempDir);
|
|
|
+ // 4. 【重点】内存流压缩,不写文件!
|
|
|
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
|
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
|
|
|
ImageWriteParam param = writer.getDefaultWriteParam();
|
|
|
+
|
|
|
+ // 保留压缩
|
|
|
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
|
|
param.setCompressionQuality(0.4f);
|
|
|
- try (FileImageOutputStream output = new FileImageOutputStream(sbFile)) {
|
|
|
- writer.setOutput(output);
|
|
|
- writer.write(null, new IIOImage(rgbImg, null, null), param);
|
|
|
- } finally {
|
|
|
- writer.dispose();
|
|
|
- }
|
|
|
|
|
|
- byte[] resultBytes;
|
|
|
- try (FileInputStream fis = new FileInputStream(sbFile)) {
|
|
|
- resultBytes = new byte[(int) sbFile.length()];
|
|
|
- fis.read(resultBytes);
|
|
|
- }
|
|
|
- sbFile.delete();
|
|
|
- tempDir.delete();
|
|
|
+ // 输出到内存流,不写文件
|
|
|
+ writer.setOutput(ImageIO.createImageOutputStream(baos));
|
|
|
+ writer.write(null, new IIOImage(rgbImg, null, null), param);
|
|
|
+
|
|
|
+ // 5. 清理
|
|
|
+ writer.dispose();
|
|
|
+ img.flush();
|
|
|
+ rgbImg.flush();
|
|
|
+
|
|
|
+ // 6. 压缩后的字节 -> 转 Base64 返回
|
|
|
+ byte[] resultBytes = baos.toByteArray();
|
|
|
+ baos.close();
|
|
|
+
|
|
|
return Base64.getEncoder().encodeToString(resultBytes);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 保存图片并返回尺寸和大小(对应 Python 中的 ys_photo_new)
|
|
|
+ * 【已改造】:不创建任何文件,纯流处理,解决服务器文件权限问题
|
|
|
*/
|
|
|
public double[] ysPhotoNew(byte[] imageBytes, String imgName) throws Exception {
|
|
|
- File tempDir = new File(imagesPath + "huatai/");
|
|
|
- if (!tempDir.exists()) {
|
|
|
- tempDir.mkdirs();
|
|
|
- }
|
|
|
- File originalFile = File.createTempFile(imagesPath + "huatai/" + "upload_temp_" + imgName, ".jpg", tempDir);
|
|
|
- try (FileOutputStream fos = new FileOutputStream(originalFile)) {
|
|
|
- fos.write(imageBytes);
|
|
|
- }
|
|
|
+ // ===================== 1. 直接从字节数组读取图片(零文件) =====================
|
|
|
+ ByteArrayInputStream bais = new ByteArrayInputStream(imageBytes);
|
|
|
+ BufferedImage img = ImageIO.read(bais);
|
|
|
+ bais.close();
|
|
|
|
|
|
- BufferedImage img = ImageIO.read(originalFile);
|
|
|
if (img == null) {
|
|
|
- throw new IOException("无法读取图片: " + originalFile.getAbsolutePath());
|
|
|
+ throw new IOException("无法读取图片:字节流解析失败");
|
|
|
}
|
|
|
|
|
|
- String width = "";
|
|
|
- String height = "";
|
|
|
-
|
|
|
+ // ===================== 2. 处理透明通道(不变) =====================
|
|
|
if (img.getColorModel().hasAlpha() || img.getType() == BufferedImage.TYPE_BYTE_INDEXED) {
|
|
|
BufferedImage rgbImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
|
|
|
rgbImg.createGraphics().drawImage(img, 0, 0, null);
|
|
|
img = rgbImg;
|
|
|
}
|
|
|
|
|
|
+ // ===================== 3. 缩放逻辑(你的原有逻辑,完全不变) =====================
|
|
|
+ String width = "";
|
|
|
+ String height = "";
|
|
|
+
|
|
|
if (width != null && !width.isEmpty() || height != null && !height.isEmpty()) {
|
|
|
int originalWidth = img.getWidth();
|
|
|
int originalHeight = img.getHeight();
|
|
|
@@ -165,17 +167,21 @@ public class UploadUtil {
|
|
|
img = resizedImg;
|
|
|
}
|
|
|
|
|
|
- File newFile = File.createTempFile(imagesPath + "huatai/" + imgName + "new", ".jpg", tempDir);
|
|
|
- ImageIO.write(img, "jpg", newFile);
|
|
|
+ // ===================== 4. 【关键】纯流获取文件大小,不写磁盘 =====================
|
|
|
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
|
+ ImageIO.write(img, "jpg", baos);
|
|
|
+ byte[] outputBytes = baos.toByteArray();
|
|
|
+ baos.close();
|
|
|
|
|
|
+ // 宽、高、大小(KB)—— 完全不需要文件
|
|
|
int newWidth = img.getWidth();
|
|
|
int newHeight = img.getHeight();
|
|
|
- long fileSize = newFile.length();
|
|
|
- double sizeKb = fileSize / 1024.0;
|
|
|
+ double sizeKb = outputBytes.length / 1024.0;
|
|
|
|
|
|
- newFile.delete();
|
|
|
- tempDir.delete();
|
|
|
+ // ===================== 5. 释放资源 =====================
|
|
|
+ img.flush();
|
|
|
|
|
|
+ // 返回和原来完全一样:[宽度,高度,大小KB]
|
|
|
return new double[]{newWidth, newHeight, sizeKb};
|
|
|
}
|
|
|
|
|
|
@@ -281,7 +287,7 @@ public class UploadUtil {
|
|
|
double[] whSize = ysPhotoNew(originalBytes, filename);
|
|
|
double fileSizeKb = whSize[2];
|
|
|
|
|
|
- File uploadFile = new File(imagesPath + "huatai/" + filename + "new.jpg");
|
|
|
+ //File uploadFile = new File(imagesPath + "huatai/" + filename + "new.jpg");
|
|
|
|
|
|
// 2. 上传文件
|
|
|
HttpHeaders uploadHeaders = new HttpHeaders();
|
|
|
@@ -307,7 +313,16 @@ public class UploadUtil {
|
|
|
String uploadUrl = "https://img-web.pc.ehuatai.com/app/ImgFileUpload/upload.do";
|
|
|
|
|
|
MultiValueMap<String, Object> uploadBody = new LinkedMultiValueMap<>();
|
|
|
- uploadBody.add("file", new FileSystemResource(uploadFile));
|
|
|
+ //uploadBody.add("file", new FileSystemResource(uploadFile));
|
|
|
+ // ByteArrayResource 代替 FileSystemResource,不需要创建文件
|
|
|
+ ByteArrayResource resource = new ByteArrayResource(originalBytes) {
|
|
|
+ @Override
|
|
|
+ public String getFilename() {
|
|
|
+ // 必须重写,否则上传文件名会为null
|
|
|
+ return filename + ".jpg";
|
|
|
+ }
|
|
|
+ };
|
|
|
+ uploadBody.add("file", resource);
|
|
|
uploadBody.add("token", this.token);
|
|
|
uploadBody.add("bucket", getUpdataValue("typeTreeNodeVo.bucket"));
|
|
|
uploadBody.add("storageType", getUpdataValue("storageType"));
|