1、准备下环境
下面简单记录一下实现过程。
首先这个是有个前提条件,包含blob的表里得有1个列是写的真实文件名带扩展后缀,要不然导出的文件没法知道是什么类型的文件。比如说你这个列里即有pdf也有word还有jpg或者压缩包啥的有。
实验基础环境准备如下:
1、准备sqldeveloper软件,下最新版本就行,别搞低版本过来。
2、解锁scott用户,创建一张数据表table_log_test(别问我为啥叫这不搭边的名,测试时随便写的),这张表的数据结构如下表所示:
ID |
VARCHAR2(20 BYTE) |
CONTENT |
BLOB |
FILE_NAME |
VARCHAR2(200 BYTE) |
创建完之后,往里面创建两条数据,扔2个Excel文件
3、数据创建成功后,对数据表进行导出,可以选左侧树中找到数据表,右键--导出(根据实际情况,这里你也可以写sql筛选一下,在结果哪里也可以右键导出。)
参照下图配置:
取消“导出DDL”
勾选“导出数据”
格式修改为“loader"
另存为修改为”单独目录“
文件修改为”你要导出存储BLOB的目录“,这里我选择D:lob。
然后点击下一步
继续下一步
点完成导出文件到本地
导出后显示如下目录内容如下
其中”表名xxxx-xxx-xxx.ldr“命名的就是blob文件
其中”表名.ldr"命名的文件就是记录数据表列内容的文件,
其中”表名.ctl"命名的文件就是控制文件,总的来就是sqlloader那一套东西给图形化了,省了不少事。
至此,基本测试环境准备完毕。下面要说的就是两种把blob导出的原始文件变成真实可用的文件。
2、方法1
--方法1,官方文档的方法
说白了就是使用python脚本进行对原始文件重命名,哈哈哈。
唯一坑的地方就是官方文档里贴出来的python脚本没有格式化,完全没法用,我擦。我和大佬研究了半天才用上。
而且官方文档还给了这么一句,大致就是python脚本只用来Demo的。不是产品,不受支持
还给了你另一个选择,就是一会要说的方法2要说到的用SQLCL+JS脚本来执行。
话接回方法1,虽说是Demo,好歹给格式化一下文件啊,给的脚本长这样。。。。。。。,没有缩进空格的脚本粘贴出来根本无法执行啊。
后来大佬给重新加工了一下脚本,改完之后长这样(使用这个得严格按照说明的3列来进行导出,调换顺序名就串了。。。。):
#该脚本是针对3列,序号|原始文件名|真实文件名,顺序不能错
import os
zip_location = input("输入目录:")
hdr_file_name = input("输入文件名: ")
f = open(zip_location+"\"+hdr_file_name, "r")
command_string = str(f.readline()).split("{EOL}")
#cleaning the command list
def command_clean(command_string):
for i in command_string:
if (i == "" ):
command_string.remove(i)
#cleaning up file name
def clean_file_name(name):
name = name.replace('"', "")
return name
#creating a copy of the specified file and renaming it
def copy_rename(file_name, file_to_name):
file_path = zip_location + "\" #file location where it will be renamed and stored.
os.rename(file_path + file_to_name,file_path + file_name)
#extracting and separating the file name and file to be renamed (delimiter is the | symbol)
def command_extract(command_string):
for s in command_string:
sep = s.split("|")
cmd1 = sep[2].split("\")[-1]
cmd2 = sep[1].strip('"')
file_name = clean_file_name(cmd1)
copy_rename(file_name,cmd2)
command_clean(command_string)
command_extract(command_string)
print('不报错就成功了')
把脚本拷贝到D:lobDATA_TABLE目录下,取名export_data_3column.py
在cmd中登录到该目录下
执行脚本
文件太少了,一闪而过。再检查目录,blob文件己经变成实际的文件名,并可以正常打开查看了。
3、方法2
--方法2,官方文档上说的另1个SQLCL+JS脚本
SQLcl可以认为是SQLPlus的新版本,基于Oracle SQL Developer中的脚本引擎,并附加到一个基于java的命令行界面。除了在命令行上提供更现代的工作方式之外,SQLcl还引入了SQLPlus本身所缺少的新命令和特性。
如何获取SQLcl?
JS脚本一定要在sqlcl下执行!!!
在https://www.oracle.com/database/technologies/appdev/sqlcl.html进行下载,下载后,解压到D盘目录下d:sqlcl
说明一下,运行sqlcl要用JAVA支持,不要下最新版本的JAVA,我试了就出乱码。要用这个版本没毛病,对应的安装包名
jdk-11.0.19_windows-x64_bin.exe
安装JAVA后,配置下JAVA_HOME、配置下系统PATH变量,顺便把sqlcl的bin目录也添加进去,我就不赘述了相信大家都会
配置成功之后,把js脚本放到D:lobDATA_TABLE目录下。
脚本内容如下:
script
// issue the SQL
var binds = {}
var ret = util.executeReturnList('select id,file_name,content from table_log_test',binds);
// loop the results
for (i = 0; i < ret.length; i++) {
// debug IS nice
ctx.write( ret[i].ID + "t" + ret[i].FILE_NAME+ "n");
// GET the BLOB stream
var blobStream = ret[i].CONTENT.getBinaryStream(1);
// GET the path/file handle TO WRITE TO
var path = java.nio.file.FileSystems.getDefault().getPath(ret[i].FILE_NAME);
// dump the file stream TO the file
java.nio.file.Files.copy(blobStream,path);
}
/
!dir
如果你的环境不同看一下说明,注意修改他里的的列名对应你的名称
The file name the blob column names can be changed in the query, but then you’ll ALSO need to change the CONTENT and FILE_NAME attributes for the ret[i] array mentioned on lines 10, 13, & 16.
同样cmd切换到D:lobDATA_TABLE目录下,先执行
sql scott/tigger@192.168.100.20:1521/orcl
登录到数据库
@js_blob.sql执行脚本
执行成功后,显示如下, 文件可以正常查看,问题是文件数量翻倍了。。。。
至此演示结束
4、测试中遇到的坑
坑的地方有2个
第1个是python脚本要严格按照顺序执行,如果你的数据表不是按这个顺序,你可select 调整一下顺序再导出来(这里也可以跟据查询结果筛选文件),然后再按脚本执行,否则你就要修改脚本里的改名规则。
第2个就是写JS的大佬文档里原文FOR用的大写,我研究了好几个小时,一直报i=0;错误,
我后来 才发现下面评论区有人指出错误。。。。。早知先看评论了。哎
文档参考
如何使用sqldeveloper导出blob
https://www.thatjeffsmith.com/archive/2014/05/exporting-multiple-blobs-with-oracle-sql-developer/#:~:text=Open%20the%20Cart%20This%20is%20easy%2C%20just%20access,don%E2%80%99t%20want%20included.%20Click%20the%20%E2%80%98Export%20Cart%E2%80%99%20button
使用sqlcl+js脚本还原真实文件名
https://www.thatjeffsmith.com/archive/2020/07/using-sqlcl-to-write-out-blobs-to-files-in-20-lines-of-js/
官方文档How to Export Multiple BLOB Data, Each To Their Respective Filename (Doc ID 2753958.1)
https://support.oracle.com/knowledge/Middleware/2753958_1.html