Мне не хватает чего-нибудь, чтобы отправить длинную aud ios записанную в веб-браузере на oracle apex? - PullRequest
1 голос
/ 21 февраля 2020

Я пытаюсь отправить записанное аудио из веб-браузера на Oracle Apex, но возникает проблема, когда звук достаточно длинный. Код работает очень хорошо, когда аудио менее двух минут.

Что я знаю, данные отправляются по URL, поэтому они отправляются в текстовом формате. Oracle имеет ограничение в 32 КБ для строки, поэтому, если большой двоичный объект превышает этот предел, его необходимо отправить в массиве, разделенном на части по 30 КБ каждая. Поэтому я подозреваю, что массив отправляется не в правильном формате, но я не знаю, как это подтвердить.

Я использую следующий код: (Я создал плагин для Apex для отправить аудио)

  • Фрагмент в Javascript, который отправляет аудио:
    // builds a js array from long string
    clob2Array: function(clob, size, array) {
        loopCount = Math.floor(clob.length / size) + 1;
        for (var i = 0; i < loopCount; i++) {
            array.push(clob.slice(size * i, size * (i + 1)));
        }
        return array;
    },
    // converts DataURI to base64 string
    dataURI2base64: function(dataURI) { 
        var base64 = dataURI.substr(dataURI.indexOf(',') + 1); 
        return base64;
    },

    blobToDataURL: function(blob, callback) {
        var a = new FileReader();
        a.onload = function(e) {callback(e.target.result);}
        a.readAsDataURL(blob);
    },
    // save to DB function
    save2Db: function(pAjaxIdentifier, pRegionId, pAudio, callback) { 
        apexAudio.blobToDataURL(pAudio, function(data){ 
            // audio DataURI to base64
            var base64 = apexAudio.dataURI2base64(data);
            // split base64 clob string to f01 array length 30k
            var f01Array = new Array(); 
            f01Array = apexAudio.clob2Array(base64, 30000, f01Array); 

            // Apex Ajax Call        
            apex.server.plugin(pAjaxIdentifier, {
                f01: f01Array,
            }, {
                dataType: 'html',
                // SUCESS function
                success: function() {
                    // add apex event
                    $('#' + pRegionId).trigger('apexaudio-saved-db');
                    // callback
                    callback();
                },
                // ERROR function
                error: function(xhr, pMessage) {
                    // add apex event
                    $('#' + pRegionId).trigger('apexaudio-error-db');
                    console.log('save2Db: apex.server.plugin ERROR:', pMessage);
                    // callback
                    callback();
                }
            });
        });  
    } 

  • Код PL / SQL, который получает adn, преобразует массив строк в blob

    DECLARE
      --
      l_collection_name VARCHAR2(100);
      l_blob            BLOB;
      l_filename        VARCHAR2(100);
      l_mime_type       VARCHAR2(100);
      l_token           VARCHAR2(32000);
      --
    BEGIN
      -- get defaults
      l_filename  := 'audio_' || to_char(SYSDATE, 'YYYYMMDDHH24MISS') || '.webm';
      l_mime_type := 'audio/webm';

      -- build BLOB from f01 30k Array
      dbms_lob.createtemporary(l_blob,
                               TRUE,
                               dbms_lob.session);

      FOR i IN 1 .. apex_application.g_f01.count LOOP
        l_token := wwv_flow.g_f01(i);

        IF length(l_token) > 0 THEN
            dbms_lob.append(l_blob                                
                           ,to_blob(utl_encode.base64_decode(utl_raw.cast_to_raw(l_token))));                     
        END IF;
      END LOOP;

      l_collection_name := 'APEX_AUDIO';

      APEX_COLLECTION.CREATE_OR_TRUNCATE_COLLECTION(
        p_collection_name => l_collection_name);


      -- add collection member (only if BLOB not null)
      IF dbms_lob.getlength(l_blob) IS NOT NULL THEN

        apex_collection.add_member(p_collection_name => l_collection_name,
                                   p_c001            => l_filename, -- filename
                                   p_c002            => l_mime_type, -- mime_type
                                   p_d001            => SYSDATE, -- date created
                                   p_blob001         => l_blob); -- BLOB audio content
      END IF;
    END;

Повторяю, код работает отлично, если звук короткий, но если он длинный, возникает следующая ошибка:

2020-02-20T20:09:27.169Z SEVERE <P-fvMwI2WpKybDySZRumRQ> java.sql.SQLException: ORA-06550: line 2, column 2:
PLS-00306: number or wrong type arguments when calling 'AJAX'
ORA-06550: line 2, column 2:
PL/SQL: Statement ignored

InternalServerException [statusCode=500, reasons=[]]
        at oracle.dbtools.apex.ModApexContext.handleError(ModApexContext.java:288)
        at oracle.dbtools.apex.OWA.execute(OWA.java:206)
        at oracle.dbtools.apex.ModApex.handleRequest(ModApex.java:310)
        at oracle.dbtools.apex.ModApex.doPost(ModApex.java:188)
        at oracle.dbtools.apex.ModApex.service(ModApex.java:112)
        at oracle.dbtools.http.entrypoint.Dispatcher.dispatch(Dispatcher.java:126)
        [...]

Технология :

  • Oracle 12 c
  • Oracle Apex 19,2
  • Ords 19,4
  • Tomcat 8

1 Ответ

1 голос
/ 22 февраля 2020

Таким образом, вы отправляете свой запрос, используя AJAX с типом контента "application / x- www-form-urlencoded". Tomcat ограничивает максимально допустимый размер POST (по умолчанию 2 МБ). Чтобы заставить его работать в APEX, у вас есть, возможно, 2 способа

1) Выполнить какую-то двойную загрузку по частям, поэтому сначала вы разбиваете сам файл, например, file.slice (), а затем создаете массив 30k base64 порция каждого файла и загрузка этого, порция по чанку

2) Используйте тип контента "multipart / form-data" с отправкой формы, таким образом, здесь вы не используете ограничение Tomcats в 2 МБ.

Я когда-то создал плагин для загрузки файлов go, просто взгляните на эту функцию:

https://github.com/Dani3lSun/apex-plugin-dropzone/blob/90a82f4bb83fee9d78458af790560fb6c5b77978/server/js/apexdropzone.js#L378

Загруженный файл будет вставляется в apex_application_files автоматически, оттуда вы можете получить его:

https://github.com/Dani3lSun/apex-plugin-dropzone/blob/90a82f4bb83fee9d78458af790560fb6c5b77978/source/render_region.sql#L332

Я не рекомендовал бы делать это с ORDS, когда вы можете сделать это внутри вашего APEX приложение, таким образом, вы должны иметь дело с безопасностью, дополнительной аутентификацией и т. д. c ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...