Oracle 19c中UTL_FILE写入docx文件后损坏问题求助
Oracle 19c中UTL_FILE导出BLOB生成docx文件损坏问题
环境
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
问题描述
我们通过存储过程读取tab1表BLOB列中的docx文件数据,使用UTL_FILE写入指定目录。BLOB中的文件可正常下载打开,但写入目录后的文件却损坏,无法正常打开。以下是写入文件的代码片段:
DECLARE l_file UTL_FILE.FILE_TYPE; l_buffer RAW(32767); l_amount BINARY_INTEGER := 32767; l_pos INTEGER := 1; l_blob BLOB; l_blob_len INTEGER; BEGIN SELECT blob_file INTO l_blob FROM tab1 WHERE id=1; l_blob_len := DBMS_LOB.getlength(l_blob); l_file := UTL_FILE.fopen('DB_DIR','file.docx','wb', 32767); WHILE l_pos < l_blob_len LOOP DBMS_LOB.read(l_blob, l_amount, l_pos, l_buffer); UTL_FILE.put_raw(file => l_file , buffer => l_buffer, autoflush => true); l_pos := l_pos + l_amount; END LOOP; UTL_FILE.fclose(l_file); EXCEPTION WHEN OTHERS THEN IF UTL_FILE.is_open(l_file) THEN UTL_FILE.fclose(l_file); END IF; RAISE; END; /
问题原因与修复方案
文件损坏的核心问题有两个:
- 循环条件错误:原代码使用
l_pos < l_blob_len作为循环条件,当剩余数据长度不足32767字节时,最后一段数据会被跳过,导致文件末尾缺失字节。 - 固定读取长度未动态调整:最后一次读取时,剩余BLOB数据长度可能小于32767,固定请求32767字节会导致缓冲区数据异常或写入多余空字节。
修复后的完整代码:
DECLARE l_file UTL_FILE.FILE_TYPE; l_buffer RAW(32767); l_amount BINARY_INTEGER := 32767; l_pos INTEGER := 1; l_blob BLOB; l_blob_len INTEGER; BEGIN SELECT blob_file INTO l_blob FROM tab1 WHERE id=1; l_blob_len := DBMS_LOB.getlength(l_blob); l_file := UTL_FILE.fopen('DB_DIR','file.docx','wb', 32767); -- 修正循环条件,动态调整每次读取长度 WHILE l_pos <= l_blob_len LOOP -- 取剩余长度和32767的较小值,避免读取越界 l_amount := LEAST(32767, l_blob_len - l_pos + 1); DBMS_LOB.read(l_blob, l_amount, l_pos, l_buffer); UTL_FILE.put_raw(file => l_file, buffer => l_buffer, autoflush => true); l_pos := l_pos + l_amount; END LOOP; UTL_FILE.fclose(l_file); EXCEPTION WHEN OTHERS THEN IF UTL_FILE.is_open(l_file) THEN UTL_FILE.fclose(l_file); END IF; RAISE; END; /
验证方式
修复后可通过以下步骤确认文件完整性:
- 对比原BLOB长度(
l_blob_len的值)与生成文件的字节数,两者必须完全一致。 - 直接打开生成的docx文件,确认内容可正常读取。
内容的提问来源于stack exchange,提问作者RJD
相关产品推荐
相关产品推荐

