基础技术:
本文通过实例详细讲解blob和文件的相互转换和读写(包括图片、PDF、Word、文本等各种类型的文件),实例具体步骤如下:
请参考:Oracle技术_UTL_FILE包用法详解_写出文件、读入库表 这篇文章中的第一节。
请参考:Oracle技术_UTL_FILE包用法详解_写出文件、读入库表 这篇文章中的第二节。
通过查询库中blob内容,写出到指定服务器路径下,总体过程如下:
(1)通过UTL_FILE.FOPEN方法找到对应路径,创建文件,并且给出写入规则。
(2)通过DBMS_LOB.READ方法将Blob循环读到临时变量中,该变量就是要写到文件中的数据。
(3)通过UTL_FILE.PUT_RAW方法向文件中写入内容(UTL_FILE.PUT_RAW方法是写入RAW类型的数据,一般来说RAW容量更大,用的更加广泛),同样采用循环方式分批写入。
(4)循环写入完成后,通过UTL_FILE.FCLOSE方法关闭文件,结束写出。
我们看一下具体操作,这里要创建一个存储过程GET_ALL_BLOB来演示该功能,具体看里面的注释。
代码如下:
CREATE OR REPLACE PROCEDURE GET_ALL_BLOB(I_ID VARCHAR2) IS L_FILE UTL_FILE.FILE_TYPE; L_BUFFER RAW(32676); L_AMOUNT BINARY_INTEGER := 32676; L_POS INTEGER := 1; L_BLOB BLOB; L_BLOB_LEN INTEGER; L_FILENAME VARCHAR2(300); BEGIN SELECT F.C_BLOB INTO L_BLOB FROM TEST_BLOB F WHERE F.C_ID = I_ID; SELECT F.C_NAME INTO L_FILENAME FROM TEST_BLOB F WHERE F.C_ID = I_ID; L_BLOB_LEN := DBMS_LOB.GETLENGTH(L_BLOB); L_FILE := UTL_FILE.FOPEN('BLOB_FILE_DIR', L_FILENAME, 'wb'); DBMS_OUTPUT.PUT_LINE('===OPEN OK===' || L_FILENAME || '===' || L_BLOB_LEN); WHILE L_POS < L_BLOB_LEN LOOP DBMS_OUTPUT.PUT_LINE('===LOOP OK===' || L_AMOUNT || '===' || L_POS); DBMS_LOB.READ(L_BLOB, L_AMOUNT, L_POS, L_BUFFER); DBMS_OUTPUT.PUT_LINE('===READ OK===' || LENGTH(L_BUFFER)); --不要随意用DBMS_OUTPUT.PUT_LINE打印L_BUFFER,因为L_BUFFER可能会很大,会出异常 UTL_FILE.PUT_RAW(L_FILE, L_BUFFER, TRUE); DBMS_OUTPUT.PUT_LINE('===PUT OK==='); L_POS := L_POS + L_AMOUNT; L_BUFFER := ''; END LOOP; DBMS_OUTPUT.PUT_LINE('EXPORT OK'); UTL_FILE.FCLOSE(L_FILE); EXCEPTION WHEN UTL_FILE.INVALID_PATH THEN --无效的路径 DBMS_OUTPUT.PUT_LINE('===INVALID_PATH===' || I_ID); RAISE; WHEN UTL_FILE.INVALID_MODE THEN --无效的打开模式 DBMS_OUTPUT.PUT_LINE('===INVALID_MODE===' || I_ID); RAISE; WHEN UTL_FILE.INVALID_OPERATION THEN --无效的操作,文件打开错误会报这个异常,一般来说都是超长或打开方式byte型和非byte型 DBMS_OUTPUT.PUT_LINE('===INVALID_OPERATION===' || I_ID); RAISE; WHEN UTL_FILE.INVALID_MAXLINESIZE THEN --无效的最大长度,VARCHAR2最大4000,RAW最大32676,超过回报这个异常,所以一般要进行循环操作 DBMS_OUTPUT.PUT_LINE('===INVALID_MAXLINESIZE===' || I_ID); RAISE; WHEN UTL_FILE.ACCESS_DENIED THEN --拒绝进入指定路径,可能是授权问题 DBMS_OUTPUT.PUT_LINE('===ACCESS_DENIED===' || I_ID); RAISE; WHEN UTL_FILE.INVALID_FILEHANDLE THEN --文件处理错误,不常见 DBMS_OUTPUT.PUT_LINE('===INVALID_FILEHANDLE===' || I_ID); RAISE; WHEN UTL_FILE.WRITE_ERROR THEN --写入错误,处理该异常最好的方式是将要写入的文件简单化,然后找准错误原因 DBMS_OUTPUT.PUT_LINE('===WRITE_ERROR===' || I_ID); RAISE; WHEN NO_DATA_FOUND THEN --SELECT时候未找到数据,不是UTL_FILE的异常 DBMS_OUTPUT.PUT_LINE('===NO_DATA_FOUND===' || I_ID); UTL_FILE.FCLOSE(L_FILE); RAISE; WHEN OTHERS THEN IF UTL_FILE.IS_OPEN(L_FILE) THEN UTL_FILE.FCLOSE(L_FILE); RAISE; END IF; END GET_ALL_BLOB;
传入参数,调用该存储过程。
代码如下:
BEGIN -- Call the procedure GET_ALL_BLOB('ST2'); END;
执行后会在对应目录下生成文件(这里我blob里存的是图片),如下图:
通过DBMS_LOB读取指定文件,将读取的内容写入库中的blob字段,总体过程如下:
(1)通过DBMS_LOB.FILEOPEN方法找到对应路径,读取文件(文件一定要存在,与UTL_FILE不同的是,这里的文件类型为BFILE而不是UTL_FILE中的UTL_FILE.FILE_TYPE),并且给出读入规则,注意,我们这里不用UTL_FILE,而是用DBMS_LOB。
(2)通过EMPTY_BLOB()把一个空的Blob对象INSERT到指定库表内,并将其RETURNING赋值给临时的Blob变量。
(3)通过DBMS_LOB.LOADFROMFILE方法循环向变量中写入内容(通过DBMS_LOB.GETLENGTH获取BFILE文件的大小),通过这种方式为Blob赋值非常简单,内部的处理都由DBMS_LOB.LOADFROMFILE处理。
(4)写入完成后,通过DBMS_LOB.FILECLOSE方法关闭文件,结束读入。
我们看一下具体操作,这里要创建一个存储过程SET_ALL_BLOB来演示该功能,具体看里面的注释。
CREATE OR REPLACE PROCEDURE SET_ALL_BLOB(I_FILENAME VARCHAR2, I_ID VARCHAR2) IS L_BFILE BFILE; L_BLOB BLOB; BEGIN L_BFILE := BFILENAME('BLOB_FILE_DIR', I_FILENAME); DBMS_LOB.FILEOPEN(L_BFILE); DBMS_OUTPUT.PUT_LINE('===OPEN OK===' || I_FILENAME); INSERT INTO TEST_BLOB F (C_ID, C_NAME, C_BLOB) VALUES (I_ID, I_FILENAME, EMPTY_BLOB()) RETURNING C_BLOB INTO L_BLOB; --插入表 DBMS_OUTPUT.PUT_LINE('===INSERT OK===' || I_FILENAME); DBMS_LOB.LOADFROMFILE(L_BLOB, L_BFILE, DBMS_LOB.GETLENGTH(L_BFILE)); DBMS_OUTPUT.PUT_LINE('===LOADFROMFILE OK===' || DBMS_LOB.GETLENGTH(L_BFILE)); DBMS_LOB.FILECLOSE(L_BFILE); DBMS_OUTPUT.PUT_LINE('EXPORT OK'); COMMIT; EXCEPTION WHEN NO_DATA_FOUND THEN --SELECT时候未找到数据,不是UTL_FILE的异常 DBMS_OUTPUT.PUT_LINE('===NO_DATA_FOUND===' || I_ID); RAISE; WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('===OTHERS===' || I_ID); RAISE; END SET_ALL_BLOB;
传入参数,调用该存储过程。
代码如下:
BEGIN -- Call the procedure SET_ALL_BLOB('Test_jpg.jpg', 'ST3'); END;
执行后会将文件内容存入表中,如下图:
点击进入ooppookid的博客