base64 encode in MySQL

前端 未结 8 1271
执笔经年
执笔经年 2020-12-01 05:10

I want to select a blob col from one table, base64 encode it and insert it into another tables. Is there any way to do this without round tripping the data out of the DB and

8条回答
  •  盖世英雄少女心
    2020-12-01 05:29

    Yet another custom implementation that doesn't require support table:

    drop function if exists base64_encode;
    create function base64_encode(_data blob)
    returns text
    begin
        declare _alphabet char(64) default 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        declare _lim int unsigned default length(_data);
        declare _i int unsigned default 0;
        declare _chk3 char(6) default '';
        declare _chk3int int default 0;
        declare _enc text default '';
    
        while _i < _lim do
            set _chk3 = rpad(hex(binary substr(_data, _i + 1, 3)), 6, '0');
            set _chk3int = conv(_chk3, 16, 10);
            set _enc = concat(
                _enc
                ,                  substr(_alphabet, ((_chk3int >> 18) & 63) + 1, 1)
                , if (_lim-_i > 0, substr(_alphabet, ((_chk3int >> 12) & 63) + 1, 1), '=')
                , if (_lim-_i > 1, substr(_alphabet, ((_chk3int >>  6) & 63) + 1, 1), '=')
                , if (_lim-_i > 2, substr(_alphabet, ((_chk3int >>  0) & 63) + 1, 1), '=')
            );
            set _i = _i + 3;
        end while;
    
        return _enc;
    end;
    
    drop function if exists base64_decode;
    create function base64_decode(_enc text)
    returns blob
    begin
        declare _alphabet char(64) default 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        declare _lim int unsigned default 0;
        declare _i int unsigned default 0;
        declare _chr1byte tinyint default 0;
        declare _chk4int int default 0;
        declare _chk4int_bits tinyint default 0;
        declare _dec blob default '';
        declare _rem tinyint default 0;
        set _enc = trim(_enc);
        set _rem = if(right(_enc, 3) = '===', 3, if(right(_enc, 2) = '==', 2, if(right(_enc, 1) = '=', 1, 0)));
        set _lim = length(_enc) - _rem;
    
        while _i < _lim
        do
            set _chr1byte = locate(substr(_enc, _i + 1, 1), binary _alphabet) - 1;
            if (_chr1byte > -1)
            then
                set _chk4int = (_chk4int << 6) | _chr1byte;
                set _chk4int_bits = _chk4int_bits + 6;
    
                if (_chk4int_bits = 24 or _i = _lim-1)
                then
                    if (_i = _lim-1 and _chk4int_bits != 24)
                    then
                        set _chk4int = _chk4int << 0;
                    end if;
    
                    set _dec = concat(
                        _dec
                        ,                        char((_chk4int >> (_chk4int_bits -  8)) & 0xff)
                        , if(_chk4int_bits >  8, char((_chk4int >> (_chk4int_bits - 16)) & 0xff), '\0')
                        , if(_chk4int_bits > 16, char((_chk4int >> (_chk4int_bits - 24)) & 0xff), '\0')
                    );
                    set _chk4int = 0;
                    set _chk4int_bits = 0;
                end if;
            end if;
            set _i = _i + 1;
        end while;
    
        return substr(_dec, 1, length(_dec) - _rem);
    end;
    

    Gist

    You should convert charset after decoding: convert(base64_decode(base64_encode('ёлка')) using utf8)

提交回复
热议问题