Oracle
 sql >> Database >  >> RDS >> Oracle

Trova e sostituisci la stringa all'interno di BLOB per il lavoro o il file Excel

I file di Microsoft Word ed Excel non sono file di testo su cui puoi semplicemente sostituire il testo e che sicuramente non funzioneranno con un BLOB . docx e xlsx i file sono in realtà file zip (prova a cambiare l'estensione del file e a decomprimere per vedere di persona) che contengono una definizione XML del documento. Quindi dovrai:

  1. Decomprimi il file
  2. Convertire il file che deve essere modificato da un BLOB a un CLOB
  3. Modifica il contenuto del file XML corretto
  4. Riconvertire il file in un BLOB da un CLOB
  5. Aggiungi nuovamente il file modificato nel file zip

Ho scritto il codice seguente come esempio su come sostituire un docx file. Per xlsx file, ogni foglio Excel è contenuto in un file XML diverso, quindi dovrai modificare leggermente il codice per farlo funzionare con entrambi i tipi di file.

Il codice utilizza APEX_ZIP pacchetto che semplifica notevolmente il lavoro con i file zip e rende anche il codice di esempio un po' più chiaro su cosa sta succedendo. Se non hai APEX installato, dovrai capire come decomprimere/ricomprimere i file usando i pacchetti Oracle che hai.

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;