powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / decoding clob base64 to blob
7 сообщений из 7, страница 1 из 1
decoding clob base64 to blob
    #39987004
mlc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет.

Прочитал на форуме с десяток тем по сабжу, но пока все тщетно.
Основная проблема вот в чем: есть clob файл, в котором закодирован пдф файл в base64binary. Соответственно задача раскодировать и сохранить в blob. Казалось бы, все просто, но что-то не взлетает. Пробовал раскодировать двумя разными способами, но сохраненный blob после раскодировки не открывается.
Пробовал раскодировать clob в онлайн декодере, вот тут Base64 Decode File , просто вставив содержимое из clob'a, получил на выходе корректный pdf, который даже открывается.

первый способ перекодировки
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
  declare
    vblob    blob;
    voffset  integer := 1;
    vbufchar varchar2(3200);
    vbufraw  raw(32000);
    vbufsize binary_integer := 3200;
  begin
    dbms_lob.createtemporary(vblob, true);
    for j in (select * from temp_table_dropme)
    loop
        for i in 1 .. ceil(dbms_lob.getlength(j.pfdata) / vbufsize) loop
          dbms_lob.read(j.pfdata, vbufsize, voffset, vbufchar);
          vbufraw := utl_encode.base64_decode(utl_raw.cast_to_raw(vbufchar));
          dbms_lob.writeappend(vblob, utl_raw.length(vbufraw), vbufraw);
          voffset := voffset + vbufsize;
        end loop;
    end loop;

    update temp_table_dropme set base64new = vblob;
  end;

второй способ перекодировки
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
declare
  v_blob blob;
  o1 integer;
  o2 integer;
  c integer;
  w integer;
begin
    for i in (select * from temp_table_dropme)
    loop
      o1 := 1;
      o2 := 1;
      c := 0;
      w := 0;
      dbms_lob.createtemporary(v_blob, true);
      dbms_lob.converttoblob(v_blob, i.pfdata, length(i.pfdata), o1, o2, 0, c, w);
    end loop;
  
  update temp_table_dropme set base64new = v_blob;
end clob2blob;


Если сравнивать файл из онлайн декодера и файл, полученный первым способом, то первые 23 тысячи символов совпадают, а потом начинается каша. Второй способ формирует blob, который даже и близко не похож на файл из онлайн декодера.
Из тем на форуме понял только, что рвать base64-данные на куски произвольным образом не очень хорошая идея, но что с этим делать, пока не догнал.

Собственно, может знает кто, почему закодированный pdf файл не хочет раскодироваться штатными оракловыми средствами?
...
Рейтинг: 0 / 0
decoding clob base64 to blob
    #39987099
mlc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mlc,

Сейчас понял, что второй способ просто конвертирует clob в blob, не декодируя при этой содержимое.
Но вопрос по врежнему остается - почему первый способ тогда не работает.
...
Рейтинг: 0 / 0
decoding clob base64 to blob
    #39987130
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mlcпочему первый способ тогда не работает.
Потому что в нём баг. Или даже целая пачка.

Начнём с того, что размер буфера должен делиться на три без остатка.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
decoding clob base64 to blob
    #39987136
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
Начнём с того, что размер буфера должен делиться на три без остатка.

Виноват, опять маразм. Делиться надо на четыре, так что с по крайней мере размером у буфера всё нормально.
...
Рейтинг: 0 / 0
decoding clob base64 to blob
    #39987154
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Способ определения количества чтений странный. Полагается на то, что буфер всегда прочитается на полный размер и условие цикла вычисляется только однажды. Лучше читать пока не получишь NO_DATA_FOUND.
2. Размер буфера не восстанавливается до исходной величины перед следующим чтением.
3. Временный блоб не закрывается из-за чего следующее содержимое дописывается в уже существующий блоб.
4. Смещение не восстанавливается перед обработкой следующего блоба. Это должно сходу выбрасывать исключение, но, похоже, у тебя с таблице всего одна запись.

В общем, отлаживайся, проверяй что каждый кусок читается, декодируется и дописывается корректно.
...
Рейтинг: 0 / 0
decoding clob base64 to blob
    #39987188
mlc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

Спасибо, попробую.
...
Рейтинг: 0 / 0
decoding clob base64 to blob
    #39987225
mlc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все оказалось гораздо прозаичнее, чем можно себе представить. Знал бы матчасть, не троил бы.
В данном контексте я не учел, как формируется и передается вложение в рамках BASE64 и MIME .
https://en.wikipedia.org/wiki/Base64#MIME MIME does not specify a fixed length for Base64-encoded lines, but it does specify a maximum line length of 76 characters . Additionally it specifies that any extra-alphabetic characters must be ignored by a compliant decoder, although most implementations use a CR/LF newline pair to delimit encoded lines.
base64#MIME
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
JVBERi0xLjQKJeLjz9MKMiAwIG9iago8PC9MZW5ndGggMTAvRmlsdGVyL0ZsYXRlRGVjb2RlPj5z
dHJlYW0KeJwr5AIAAO4AfAplbmRzdHJlYW0KZW5kb2JqCjMgMCBvYmoKPDwvRmlsdGVyL0ZsYXRl
RGVjb2RlL0xlbmd0aCAzNzI2Pj5zdHJlYW0KeJzVXEtzGzcSZsE3+uBoE+8mh2zx6BzCDB4DzDgP
b1S24zixU95VtjaULdl60hK1jpx1Yu1fyC9JbvsPt7uB7sHwJcpyscJiieyZwaO/RgON+QDotLu+
0bW+VxW+t7HXvbPRfdQ1vft4V/cK+OB35Uxv46T7yV3d00Vv46B746ONI0wL1/B5edgt+mXvF8pY
...
L1NpemUgNDIvUm9vdCA0MCAwIFIvSW5mbyA0MSAwIFIvSUQgWzwwYjQzYWZkODlhMmVhODMxMWQ5
NzdjZjJkMjg0MjhhZj48MGI0M2FmZDg5YTJlYTgzMTFkOTc3Y2YyZDI4NDI4YWY+XT4+CiVpVGV4


Соответственно и мой CLOB имеет символы перевода строки CHR(10). Если его не убирать и декодировать с ним, то имеем то, что имеем.
При декодировании необходимо убрать все лишние переводы строк и потом уже декодировать:
решение
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
  declare
    vclob    clob;
    vblob    blob;
    voffset  integer := 1;
    vbufchar varchar2(32000);
    vbufraw  raw(32000);
    vbufsize binary_integer := 32000;
  begin
    for j in (select * from temp_table_dropme)
    loop
        -- убираем CR и LF
        dbms_lob.createtemporary(vclob, true);
        while voffset < dbms_lob.getlength(j.pfdata) loop
            vbufchar := replace(replace(dbms_lob.substr(j.pfdata, vbufsize, voffset), chr(13), null), chr(10), null);
            dbms_lob.writeappend(vclob, length(vbufchar), vbufchar);
            voffset := voffset + vbufsize;
        end loop;
    
        -- декодируем clob
        dbms_lob.createtemporary(vblob, true);
        voffset := 1;
        while voffset < dbms_lob.getlength(vclob) loop
          vbufraw := utl_encode.base64_decode(utl_raw.cast_to_raw(dbms_lob.substr(vclob, vbufsize, voffset)));
          dbms_lob.writeappend(vblob, utl_raw.length(vbufraw), vbufraw);
          voffset := voffset + vbufsize;
        end loop;
    end loop;

    -- vblob
  end;
/

...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / decoding clob base64 to blob
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]