UTL_COMPRESS Архивирование нескольких BLOB-объектов
Пожалуйста, кто-нибудь может мне помочь с информацией. В приведенном ниже коде для архивирования нескольких файлов мы используем несколько индексов. Можете ли вы указать, почему используются эти конкретные индексы:
little_endian( t_clen - 18 )
- Почему 18 прошло здесь?for CRC32 : dbms_lob.substr( t_blob, 4, t_clen - 7 )
- Почему 4 и 7 пройдены здесь?dbms_lob.append( p_zipped_blob, dbms_lob.substr( t_blob, t_clen - 18, 11 ) ); -- compressed content
- Почему 11 прошло здесь?И другие индексы, используемые в коде, такие как: 26,30,32 и т. Д.?
declare
g_zipped_blob blob;
b_dl_file1 BLOB;
b_dl_file2 BLOB;
b_dl_file3 BLOB;
-
function little_endian( p_big in number, p_bytes in pls_integer := 4 )
return raw
is
begin
return utl_raw.substr( utl_raw.cast_from_binary_integer( p_big, utl_raw.little_endian ), 1, p_bytes );
end;
--
procedure add1file
( p_zipped_blob in out blob
, p_name in varchar2
, p_content in blob
)
is
t_now date;
t_blob blob;
t_clen integer;
begin
t_now := sysdate;
t_blob := utl_compress.lz_compress( p_content );
t_clen := dbms_lob.getlength( t_blob );
if p_zipped_blob is null
then
dbms_lob.createtemporary( p_zipped_blob, true );
end if;
dbms_lob.append( p_zipped_blob
, utl_raw.concat( hextoraw( '504B0304' ) -- Local file header signature
, hextoraw( '1400' ) -- version 2.0
, hextoraw( '0000' ) -- no General purpose bits
, hextoraw( '0800' ) -- deflate
, little_endian( to_number( to_char( t_now, 'ss' ) ) / 2
+ to_number( to_char( t_now, 'mi' ) ) * 32
+ to_number( to_char( t_now, 'hh24' ) ) * 2048
, 2
) -- File last modification time
, little_endian( to_number( to_char( t_now, 'dd' ) )
+ to_number( to_char( t_now, 'mm' ) ) * 32
+ ( to_number( to_char( t_now, 'yyyy' ) ) - 1980 ) * 512
, 2
) -- File last modification date
, dbms_lob.substr( t_blob, 4, t_clen - 7 ) -- CRC-32
, little_endian( t_clen - 18 ) -- compressed size
, little_endian( dbms_lob.getlength( p_content ) ) -- uncompressed size
, little_endian( length( p_name ), 2 ) -- File name length
, hextoraw( '0000' ) -- Extra field length
, utl_raw.cast_to_raw( p_name ) -- File name
)
);
dbms_lob.append( p_zipped_blob, dbms_lob.substr( t_blob, t_clen - 18, 11 ) ); -- compressed content
dbms_lob.freetemporary( t_blob );
end;
--
procedure finish_zip( p_zipped_blob in out blob )
is
t_cnt pls_integer := 0;
t_offs integer;
t_offs_dir_header integer;
t_offs_end_header integer;
t_comment raw(32767) := utl_raw.cast_to_raw( 'Implementation by Anton Scheffer' );
begin
t_offs_dir_header := dbms_lob.getlength( p_zipped_blob );
t_offs := dbms_lob.instr( p_zipped_blob, hextoraw( '504B0304' ), 1 );
while t_offs > 0
loop
t_cnt := t_cnt + 1;
dbms_lob.append( p_zipped_blob
, utl_raw.concat( hextoraw( '504B0102' ) -- Central directory file header signature
, hextoraw( '1400' ) -- version 2.0
, dbms_lob.substr( p_zipped_blob, 26, t_offs + 4 )
, hextoraw( '0000' ) -- File comment length
, hextoraw( '0000' ) -- Disk number where file starts
, hextoraw( '0100' ) -- Internal file attributes
, hextoraw( '2000B681' ) -- External file attributes
, little_endian( t_offs - 1 ) -- Relative offset of local file header
, dbms_lob.substr( p_zipped_blob
, utl_raw.cast_to_binary_integer( dbms_lob.substr( p_zipped_blob, 2, t_offs + 26 ), utl_raw.little_endian )
, t_offs + 30
) -- File name
)
);
t_offs := dbms_lob.instr( p_zipped_blob, hextoraw( '504B0304' ), t_offs + 32 );
end loop;
t_offs_end_header := dbms_lob.getlength( p_zipped_blob );
dbms_lob.append( p_zipped_blob
, utl_raw.concat( hextoraw( '504B0506' ) -- End of central directory signature
, hextoraw( '0000' ) -- Number of this disk
, hextoraw( '0000' ) -- Disk where central directory starts
, little_endian( t_cnt, 2 ) -- Number of central directory records on this disk
, little_endian( t_cnt, 2 ) -- Total number of central directory records
, little_endian( t_offs_end_header - t_offs_dir_header ) -- Size of central directory
, little_endian( t_offs_dir_header ) -- Relative offset of local file header
, little_endian( nvl( utl_raw.length( t_comment ), 0 ), 2 ) -- ZIP file comment length
, t_comment
)
);
end;
--
procedure save_zip
( p_zipped_blob in blob
, p_dir in varchar2 := 'MY_DIR'
, p_filename in varchar2 := 'my.zip'
)
is
t_fh utl_file.file_type;
t_len pls_integer := 32767;
begin
t_fh := utl_file.fopen( p_dir, p_filename, 'wb' );
for i in 0 .. trunc( ( dbms_lob.getlength( p_zipped_blob ) - 1 ) / t_len )
loop
utl_file.put_raw( t_fh, dbms_lob.substr( p_zipped_blob, t_len, i * t_len + 1 ) );
end loop;
utl_file.fclose( t_fh );
end;
begin
select FILE_BLOB
into b_dl_file1
from FILES
where FILE_ID = 64;
select FILE_BLOB
into b_dl_file2
from FILES
where FILE_ID = 65;
select FILE_BLOB
into b_dl_file3
from FILES
where FILE_ID = 66;
add1file( g_zipped_blob, 'test1.bin', b_dl_file1 );
add1file( g_zipped_blob, 'test2.bin', b_dl_file2 );
add1file( g_zipped_blob, 'test2.bin', b_dl_file3 );
finish_zip( g_zipped_blob );
save_zip( g_zipped_blob, 'MY_DIR', 'my.zip' );
end;