【发布时间】:2021-02-24 18:41:58
【问题描述】:
我需要查找和替换存储在数据库中的数千个文档中过时的超链接。
目前我有一些函数可以将 BLOB 转换为 CLOB 进行查找和替换,然后再转换回 BLOB。
但最终结果不会使文件保持其原始状态,例如我存储了一个 word 文档,我找到超链接 www.google.co.uk 并替换,BLOB 数据不再是 word 文档类型,我无法打开它。
是否有推荐的方法来执行上述操作。
非常感谢,
【问题讨论】:
我需要查找和替换存储在数据库中的数千个文档中过时的超链接。
目前我有一些函数可以将 BLOB 转换为 CLOB 进行查找和替换,然后再转换回 BLOB。
但最终结果不会使文件保持其原始状态,例如我存储了一个 word 文档,我找到超链接 www.google.co.uk 并替换,BLOB 数据不再是 word 文档类型,我无法打开它。
是否有推荐的方法来执行上述操作。
非常感谢,
【问题讨论】:
Microsoft Word 和 Excel 文件不是文本文件,您只能在上面替换文本,而且绝对不能与 BLOB 一起使用。 docx 和 xlsx 文件实际上是包含文档的 XML 定义的 zip 文件(尝试更改文件扩展名并解压缩以查看)。所以你需要:
BLOB 转换为CLOB
CLOB 转换回BLOB
我编写了下面的代码作为如何替换 docx 文件的示例。对于 xlsx 文件,每个 Excel 工作表都包含在不同的 XML 文件中,因此您需要稍微修改代码以使其适用于两种文件类型。
代码确实使用了APEX_ZIP 包,它极大地简化了对 zip 文件的处理,并使示例代码更清楚地了解正在发生的事情。如果您没有安装 APEX,则需要弄清楚如何使用您拥有的 Oracle 包对文件进行解压缩/重新压缩。
DECLARE
l_old_file BLOB;
l_new_file BLOB;
l_files apex_zip.t_files;
l_document BLOB;
l_clob CLOB;
l_dest_offsset INTEGER;
l_src_offsset INTEGER;
l_lang_context INTEGER := DBMS_LOB.default_lang_ctx;
l_warning INTEGER;
BEGIN
-- Get the blob you want to "correct"
SELECT blob_content
INTO l_old_file
FROM apex_application_temp_files
WHERE ROWNUM = 1;
-- Get a list of all the file names contained within the zip
l_files := apex_zip.get_files (l_old_file);
-- Loop through all the files adding each one to the new zip
FOR i IN l_files.FIRST .. l_files.LAST
LOOP
l_document := apex_zip.get_file_content (l_old_file, l_files (i));
IF l_files (i) = 'word/document.xml'
THEN
-- if the file name is word/document.xml then make the changes to it
DBMS_LOB.createTemporary (lob_loc => l_clob, cache => FALSE);
l_dest_offsset := 1;
l_src_offsset := 1;
DBMS_LOB.converttoclob (dest_lob => l_clob,
src_blob => l_document,
amount => DBMS_LOB.lobmaxsize,
dest_offset => l_dest_offsset,
src_offset => l_src_offsset,
blob_csid => DBMS_LOB.default_csid,
lang_context => l_lang_context,
warning => l_warning);
--------------------
-- This is where you would do any replacements
--------------------
l_clob := REPLACE (l_clob, 'www.google.co.uk', 'www.google.com');
--------------------
l_dest_offsset := 1;
l_src_offsset := 1;
DBMS_LOB.CONVERTTOBLOB (dest_lob => l_document,
src_clob => l_clob,
amount => DBMS_LOB.lobmaxsize,
dest_offset => l_dest_offsset,
src_offset => l_src_offsset,
blob_csid => DBMS_LOB.default_csid,
lang_context => l_lang_context,
warning => l_warning);
END IF;
apex_zip.add_file (l_new_file, l_files (i), l_document);
END LOOP;
apex_zip.finish (l_new_file);
--Do whatever you want with the "new" file here
END;
【讨论】:
.zip 并尝试解压,是否解压成功,修改后的 XML 文件是否如您所愿?