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
相关产品推荐
相关产品推荐

