Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Suchen und ersetzen Sie die Zeichenfolge in BLOB for Work oder Excel-Datei

Microsoft Word- und Excel-Dateien sind keine Textdateien, in denen Sie einfach Text ersetzen können, und die definitiv nicht mit einem BLOB funktionieren . docx und xlsx Dateien sind eigentlich ZIP-Dateien (versuchen Sie, die Dateierweiterung zu ändern und zu entpacken, um es selbst zu sehen), die eine XML-Definition des Dokuments enthalten. Sie müssen also:

  1. Entpacken Sie die Datei
  2. Konvertieren Sie die Datei, die geändert werden muss, von einem BLOB zu einem CLOB
  3. Ändern Sie den Inhalt der richtigen XML-Datei
  4. Konvertieren Sie die Datei zurück in ein BLOB von einem CLOB
  5. Fügen Sie die geänderte Datei wieder in die ZIP-Datei ein

Ich habe den folgenden Code als Beispiel geschrieben, wie man ein docx ersetzt Datei. Für xlsx Dateien ist jede Excel-Tabelle in einer anderen XML-Datei enthalten, sodass Sie den Code leicht ändern müssen, damit er mit beiden Dateitypen funktioniert.

Der Code verwendet den APEX_ZIP Paket, das die Arbeit mit ZIP-Dateien erheblich vereinfacht und den Beispielcode auch etwas klarer macht, was vor sich geht. Wenn Sie APEX nicht installiert haben, müssen Sie herausfinden, wie Sie die Dateien mit den vorhandenen Oracle-Paketen entpacken/rekomprimieren.

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;