Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Localize e substitua a string dentro do BLOB for Work ou Excel File


Os arquivos do Microsoft Word e Excel não são arquivos de texto nos quais você pode simplesmente substituir o texto e isso definitivamente não funcionará com um BLOB . docx e xlsx os arquivos são na verdade arquivos zip (tente alterar a extensão do arquivo e descompactar para ver por si mesmo) que contêm uma definição XML do documento. Então você vai precisar:
  1. Descompacte o arquivo
  2. Converter o arquivo que precisa ser alterado de um BLOB para um CLOB
  3. Modifique o conteúdo do arquivo XML adequado
  4. Converter o arquivo novamente em um BLOB de um CLOB
  5. Adicione o arquivo modificado de volta ao arquivo zip

Eu escrevi o código abaixo como um exemplo de como substituir um docx Arquivo. Para xlsx arquivos, cada planilha do Excel está contida em um arquivo XML diferente, portanto, você precisará modificar um pouco o código para que funcione com os dois tipos de arquivo.

O código usa o APEX_ZIP pacote que simplifica muito o trabalho com arquivos zip e também torna o código de exemplo um pouco mais claro sobre o que está acontecendo. Se você não tiver o APEX instalado, precisará descobrir como descompactar/rezipar os arquivos usando os pacotes Oracle que você possui.
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;