소스 검색

影像资料上传图片写入失败

cr 5 일 전
부모
커밋
c26ba9681a
1개의 변경된 파일223개의 추가작업 그리고 38개의 파일을 삭제
  1. 223 38
      blade-service/blade-business/src/main/java/org/springblade/business/utils/FileUtils.java

+ 223 - 38
blade-service/blade-business/src/main/java/org/springblade/business/utils/FileUtils.java

@@ -24,6 +24,7 @@ import javax.imageio.IIOImage;
 import javax.imageio.ImageIO;
 import javax.imageio.ImageWriteParam;
 import javax.imageio.ImageWriter;
+import javax.imageio.stream.ImageOutputStream;
 import javax.servlet.http.HttpServletResponse;
 import java.awt.*;
 import java.awt.geom.AffineTransform;
@@ -118,52 +119,173 @@ public class FileUtils {
         }
     }
 
+//    /**
+//     * 图片缩放、压缩、旋转处理
+//     *
+//     * @param imageData
+//     * @return
+//     * @throws IOException
+//     * @throws ImageProcessingException
+//     * @throws MetadataException
+//     */
+//    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();
+//    }
+
     /**
-     * 图片缩放、压缩、旋转处理
-     *
-     * @param imageData
-     * @return
-     * @throws IOException
-     * @throws ImageProcessingException
-     * @throws MetadataException
-     */
-    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);
+     // * 图片缩放、压缩、旋转处理
+     // *
+     // * @param imageData
+     // * @return
+     // * @throws IOException
+     // * @throws ImageProcessingException
+     // * @throws MetadataException
+     //     */
+    public static byte[] compressImage(byte[] imageData) throws IOException {
+        if (imageData == null || imageData.length == 0) {
+            throw new IllegalArgumentException("图像数据不能为空");
+        }
+
+        try {
+            // 读取原始图像(处理旋转问题)
+            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));
+                    if (originalImage == null) {
+                        throw new IOException("无法读取图像数据");
+                    }
+
+                    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();
                 }
-                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();
             }
+        } catch (Exception e) {
+            // 如果EXIF处理失败,继续处理原始图像数据
+            System.err.println("处理图像EXIF信息时出错: " + e.getMessage());
         }
+
         // 缩放图像
         String formatName = "JPEG";
         ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
         BufferedImage originalImage = ImageIO.read(bais);
+
+        if (originalImage == null) {
+            throw new IOException("无法读取图像数据");
+        }
+
+        // 确保图像是兼容的格式
+        BufferedImage compatibleImage = convertToSupportedFormat(originalImage);
+
         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);
+        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+        Graphics2D g2d = resizedImage.createGraphics();
+        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+        g2d.drawImage(scaledImage, 0, 0, null);
+        g2d.dispose();
 
         // 压缩图像
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ImageIO.write(resizedImage, formatName, baos);
+        try {
+            boolean success = ImageIO.write(resizedImage, formatName, baos);
+            if (!success) {
+                throw new IOException("无法写入JPEG格式图像");
+            }
+        } catch (Exception e) {
+            // 尝试使用ImageWriter直接写入
+            writeImageWithDefaultSettings(resizedImage, baos, formatName);
+        }
 
         if (baos.size() <= sizeLimit) {
             // 图片大小已经小于等于目标大小,直接返回原始数据
@@ -178,23 +300,40 @@ public class FileUtils {
             byte[] data = baos.toByteArray();
             bais = new ByteArrayInputStream(data);
             BufferedImage compressedImage = ImageIO.read(bais);
+
+            if (compressedImage == null) {
+                throw new IOException("无法读取压缩后的图像数据");
+            }
+
             baos.reset();
 
             ImageWriter writer = null;
-            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
+            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName.toLowerCase());
+            if (!writers.hasNext()) {
+                // 尝试其他格式
+                writers = ImageIO.getImageWritersByFormatName("jpeg");
+            }
+
             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);
+            try {
+                ImageWriteParam writeParam = writer.getDefaultWriteParam();
+                if (writeParam.canWriteCompressed()) {
+                    writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+                    writeParam.setCompressionQuality(quality);
+                }
 
-            writer.setOutput(ImageIO.createImageOutputStream(baos));
-            writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
-            writer.dispose();
+                try (ImageOutputStream ios = ImageIO.createImageOutputStream(baos)) {
+                    writer.setOutput(ios);
+                    writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
+                }
+            } finally {
+                writer.dispose();
+            }
 
             float ratio = sizeLimit * 1.0f / baos.size();
             quality *= Math.sqrt(ratio);
@@ -204,6 +343,52 @@ public class FileUtils {
         return baos.toByteArray();
     }
 
+    /**
+     * 转换图像为支持的格式
+     */
+    private static BufferedImage convertToSupportedFormat(BufferedImage image) {
+        if (image == null) return null;
+
+        // 检查是否为支持的类型
+        int type = image.getType();
+        if (type != BufferedImage.TYPE_INT_RGB && type != BufferedImage.TYPE_INT_ARGB) {
+            // 转换为支持的格式
+            BufferedImage converted = new BufferedImage(
+                    image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
+            Graphics2D g = converted.createGraphics();
+            g.setColor(Color.WHITE);
+            g.fillRect(0, 0, converted.getWidth(), converted.getHeight());
+            g.drawImage(image, 0, 0, null);
+            g.dispose();
+            return converted;
+        }
+        return image;
+    }
+
+    /**
+     * 使用默认设置写入图像
+     */
+    private static void writeImageWithDefaultSettings(BufferedImage image, ByteArrayOutputStream baos, String formatName) throws IOException {
+        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName.toLowerCase());
+        if (!writers.hasNext()) {
+            writers = ImageIO.getImageWritersByFormatName("jpeg");
+        }
+
+        if (!writers.hasNext()) {
+            throw new IOException("找不到JPEG图像写入器");
+        }
+
+        ImageWriter writer = writers.next();
+        ImageWriteParam param = writer.getDefaultWriteParam();
+
+        try (ImageOutputStream ios = ImageIO.createImageOutputStream(baos)) {
+            writer.setOutput(ios);
+            writer.write(null, new IIOImage(image, null, null), param);
+        } finally {
+            writer.dispose();
+        }
+    }
+
     /**
      * 设置图片的定位、大小和合并单元格处理
      *