在Oracle中存图片,最简单的方法是使用BLOB类型。首先创建表:
CREATE TABLE images (id NUMBER PRIMARY KEY, image BLOB);
然后插入图片:用Java或PL/SQL的DBMS_LOB包读取文件二进制数据存入BLOB字段。最新技巧是用空BLOB初始化,然后APPEND数据,避免一次性加载大文件内存溢出。
方法一:BLOB字段存储
建表语句:
CREATE TABLE MY_IMAGES (
ID NUMBER PRIMARY KEY,
IMAGE_NAME VARCHAR2(100),
IMAGE_DATA BLOB
);
插入图片的PL/SQL代码:
DECLARE
v_bfile BFILE := BFILENAME('IMG_DIR', 'test.jpg');
v_blob BLOB;
BEGIN
DBMS_LOB.CREATETEMPORARY(v_blob, TRUE);
DBMS_LOB.FILEOPEN(v_bfile, DBMS_LOB.FILE_READONLY);
DBMS_LOB.LOADFROMFILE(v_blob, v_bfile, DBMS_LOB.GETLENGTH(v_bfile));
INSERT INTO MY_IMAGES (ID, IMAGE_NAME, IMAGE_DATA) VALUES (1, 'test.jpg', v_blob);
COMMIT;
END;
目录对象创建
先创建目录:CREATE OR REPLACE DIRECTORY IMG_DIR AS '/opt/images'; GRANT READ ON DIRECTORY IMG_DIR TO your_user; 这样就能从文件系统直接加载图片到BLOB了,不用Java程序中介,超级方便。
读取图片
查询BLOB:SELECT IMAGE_DATA FROM MY_IMAGES WHERE ID=1; 在前端用JDBC getBlob()获取,然后输出到浏览器response.getOutputStream(),设置Content-Type: image/jpeg,就能显示了。最新技巧是用UTL_RAW.CAST_TO_RAW转换,避免乱码。
高级技巧:压缩存储
存前压缩:用UTL_COMPRESS.LZ_COMPRESS(原blob)存入,取出用LZ_UNCOMPRESS解压。节省80%空间,尤其大图多的时候。建表时IMAGE_DATA可以是CLOB或BLOB都行,但BLOB更直接。
避免常见坑
大图片别用INSERT直接空BLOB APPEND,分块LOADBLOBFROMFILE,每次4M块。Oracle 19c后支持SecureFile LOB,性能更好,建表加 ENABLE STORAGE IN ROW。
前端显示代码
JSP示例:<img src="showImage.jsp?id=1" />
showImage.jsp: Blob blob = rs.getBlob("IMAGE_DATA"); response.setContentType("image/jpeg"); IOUtils.copy(blob.getBinaryStream(), response.getOutputStream()); 完美显示。
FAQ
Q: BLOB和CLOB哪个存图片好?
A: BLOB存二进制图片,CLOB存文本。
Q: 怎么处理超大图片?
A: 分块加载,用DBMS_LOB.LOADBLOBFROMFILE。
Q: 权限不够怎么搞?
A: GRANT READ, WRITE ON DIRECTORY IMG_DIR TO USER。
Q: 怎么删除BLOB?
A: DELETE FROM表; COMMIT; 自动释放空间。