You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle APEX Blob图片转JPEG压缩Java类开发及Blob未变化问题求助

Oracle + APEX 图片Blob转JPEG压缩的处理异常

业务背景

  • 基于Oracle数据库与APEX搭建应用,部分页面支持用户上传图片至数据库存储
  • 图片上传后需统一转换为JPEG格式并压缩
  • 原有转换压缩逻辑依赖ORDIMAGE数据库包,该包在后续Oracle版本将不再受支持

拟实现方案

  • 开发Java类完成图片格式转换、压缩的核心逻辑,将类上传至Oracle数据库执行
  • 配套创建存储过程包装器,传入待转换图片的Blob类型参数,由Java类返回转换压缩后的Blob
  • 全程不将转换后的文件临时存储到文件系统,避免额外IO开销

参考内容与待确认问题

  • 参考公开实现:Blob转JPG并更新Blob的逻辑、JPEG压缩实现
  • 待确认:当前参考的Blob转JPG方案是否支持所有图片格式的转换

异常描述

本人为Java初学者(本职为数据库开发人员),已提前验证参考的JPEG压缩代码可正常完成本地JPEG图片的压缩,但开发出出入参均为Blob的处理类后出现异常:通过JDBC从数据库取出存储为Blob的JPEG图片,调用compressJPEG方法处理后,Blob的长度始终未发生变化。

测试输出

126  23190  myimage.jpg 取出的Blob长度:4284416
副本Blob长度:4284416
调用compressJPEG(myBlobCopy)
进入compressJPEG方法
方法执行完成:Blob长度:4284416

从输出判断,压缩后的Blob未被正确返回,附完整实现代码如下:

import java.sql.*; 
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.sql.Blob;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import javax.imageio.IIOImage;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
//import java.sql.SQLException;     

class OracleConCompressBLOB{  
    public static void main(String args[]){  
        try{  
            Blob myBlob = null;
            Blob myBlobCopy = null;

            // 加载Oracle JDBC驱动
            Class.forName("oracle.jdbc.driver.OracleDriver");  
            String dbURL = "jdbc:oracle:thin:@(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = xxxx)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = xxxx) ) )";
            String strUserID = "xxxx";
            String strPassword = "xxxx";
            
            // 获取数据库连接
            Connection con=DriverManager.getConnection(dbURL,strUserID,strPassword);  
            
            // 创建查询语句,加行级锁保证Blob可更新
            Statement stmt=con.createStatement();  
            ResultSet rs=stmt.executeQuery("select PRFO_ID, PRFO_PRAX_ID , PRFO_DATEINAME, PRFO_FOTO from T_PRAFOTO where PRFO_ID = 126  FOR UPDATE");

            if (rs.next()) {
                myBlob = rs.getBlob(4);
                myBlobCopy = myBlob;
                System.out.println(rs.getInt(1)+"  "+rs.getInt(2)+"  "+rs.getString(3)+" Length of retrieved Blob: " + myBlob.length());  
                System.out.println(" Length of copy Blob: " + myBlobCopy.length());  
                System.out.println("Call compressJPEG (myBlobCopy) ");    
                compressJPEG (myBlobCopy);           
                System.out.println("Back from compressJPEG: Length of retrieved Blob: " + myBlobCopy.length());  
            }

            // 关闭数据库连接
            con.close();  
        }catch(Exception e){ 
            System.out.println(e);
        }  
    }  

    public static void compressJPEG(Blob blob) throws IOException {
        // 原本地文件处理逻辑已注释
        // File imageFile = new File("myimage.jpg");
        // File compressedImageFile = new File("myimage_compressed.jpg");
        // InputStream is = new FileInputStream(imageFile);
        // OutputStream os = new FileOutputStream(compressedImageFile);

        System.out.println("now in compressJPEG");  

        BufferedImage bufferedImage = null;
        OutputStream outputStream = null;
        float quality = 0.5f;
        try {
            // 从Blob输入流读取图片
            // BufferedImage image = ImageIO.read(is);
            bufferedImage = ImageIO.read(blob.getBinaryStream()); 
            // 获取Blob输出流,从位置0开始写入
            outputStream = blob.setBinaryStream(0); 

            // 获取JPG格式的图片写入器
            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
            if (!writers.hasNext())
                throw new IllegalStateException("No writers found");

            ImageWriter writer = (ImageWriter) writers.next();
            ImageOutputStream ios = ImageIO.createImageOutputStream(outputStream);
            writer.setOutput(ios);

            // 设置压缩参数
            ImageWriteParam param = writer.getDefaultWriteParam();
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(quality);

            // 写入压缩后的图片
            writer.write(null, new IIOImage(bufferedImage, null, null), param);

            // 清理资源
            outputStream.flush();
            ios.close();
            outputStream.close();
            writer.dispose();      
        } catch (IOException e) {
            e.printStackTrace();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
        catch(IllegalArgumentException e) {
            e.printStackTrace();
        }
    }
}

内容的提问来源于stack exchange,提问作者Holger Koelzer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.23 12:15:06