Pergunta

Eu quero selecionar um col blob de uma tabela, base64 codificá-lo e inseri-lo em outro tabelas. Existe alguma maneira de fazer isso sem tropeçar rodada os dados fora do DB e através do meu aplicativo?

Foi útil?

Solução

Eu estava olhando para a mesma coisa e eu acabamos de ver que o MySQL 5.6 tem um casal de novas funções de cadeia que suportam esta funcionalidade: TO_BASE64 e FROM_BASE64 .

Outras dicas

Funções de http://wi-fizzle.com/downloads/base64.sql conter alguns erros quando em cadeia codificada são de 32 bytes (espaço), ex base64_encode (CONCAT (CHAR (15), CHAR (32))). função aqui é corrigida

DELIMITER $$

USE `YOUR DATABASE`$$

DROP TABLE IF EXISTS core_base64_data$$
CREATE TABLE core_base64_data (c CHAR(1) BINARY, val TINYINT)$$
INSERT INTO core_base64_data VALUES 
('A',0), ('B',1), ('C',2), ('D',3), ('E',4), ('F',5), ('G',6), ('H',7), ('I',8), ('J',9),
('K',10), ('L',11), ('M',12), ('N',13), ('O',14), ('P',15), ('Q',16), ('R',17), ('S',18), ('T',19),
('U',20), ('V',21), ('W',22), ('X',23), ('Y',24), ('Z',25), ('a',26), ('b',27), ('c',28), ('d',29),
('e',30), ('f',31), ('g',32), ('h',33), ('i',34), ('j',35), ('k',36), ('l',37), ('m',38), ('n',39),
('o',40), ('p',41), ('q',42), ('r',43), ('s',44), ('t',45), ('u',46), ('v',47), ('w',48), ('x',49),
('y',50), ('z',51), ('0',52), ('1',53), ('2',54), ('3',55), ('4',56), ('5',57), ('6',58), ('7',59),
('8',60), ('9',61), ('+',62), ('/',63), ('=',0) $$

DROP FUNCTION IF EXISTS `BASE64_ENCODE`$$

CREATE DEFINER=`YOUR DATABASE`@`%` FUNCTION `BASE64_ENCODE`(input BLOB) RETURNS BLOB
    DETERMINISTIC
    SQL SECURITY INVOKER
BEGIN
    DECLARE ret BLOB DEFAULT '';
    DECLARE done TINYINT DEFAULT 0;
    IF input IS NULL THEN
        RETURN NULL;
    END IF;
each_block:
    WHILE NOT done DO BEGIN
        DECLARE accum_value BIGINT UNSIGNED DEFAULT 0;
        DECLARE in_count TINYINT DEFAULT 0;
        DECLARE out_count TINYINT;
each_input_char:
        WHILE in_count < 3 DO BEGIN
            DECLARE first_char BLOB(1);

            IF LENGTH(input) = 0 THEN
                SET done = 1;
                SET accum_value = accum_value << (8 * (3 - in_count));
                LEAVE each_input_char;
            END IF;

            SET first_char = SUBSTRING(input,1,1);
            SET input = SUBSTRING(input,2);

            SET accum_value = (accum_value << 8) + ASCII(first_char);
            SET in_count = in_count + 1;
        END; END WHILE;

        -- We've now accumulated 24 bits; deaccumulate into base64 characters
        -- We have to work from the left, so use the third byte position and shift left
        CASE
            WHEN in_count = 3 THEN SET out_count = 4;
            WHEN in_count = 2 THEN SET out_count = 3;
            WHEN in_count = 1 THEN SET out_count = 2;
            ELSE RETURN ret;
        END CASE;

        WHILE out_count > 0 DO BEGIN
            BEGIN
                DECLARE out_char CHAR(1);
                DECLARE base64_getval CURSOR FOR SELECT c FROM core_base64_data WHERE val = (accum_value >> 18);
                OPEN base64_getval;
                FETCH base64_getval INTO out_char;
                CLOSE base64_getval;
                SET ret = CONCAT(ret,out_char);
                SET out_count = out_count - 1;
                SET accum_value = accum_value << 6 & 0xffffff;
            END;
        END; END WHILE;
        CASE
            WHEN in_count = 2 THEN SET ret = CONCAT(ret,'=');
            WHEN in_count = 1 THEN SET ret = CONCAT(ret,'==');
            ELSE BEGIN END;
        END CASE;

    END; END WHILE;
    RETURN ret;
END$$

DELIMITER ;
SELECT `id`,`name`, TO_BASE64(content) FROM `db`.`upload`

isso irá converter o valor blob a partir coluna conteúdo para string base64. Em seguida, você pode fazer com esta corda que quiser, mesmo inseri-lo em outra tabela

parece com nenhum, embora foi solicitado , e há uma UDF para -lo.

Edit: Ou há ... este . Ugh.

Para os interessados, estas são as únicas alternativas até agora:

1) usando essas funções:

http://wi-fizzle.com/downloads/base64.sql

2) Se você já tem o sys_eval UDF , (Linux) você pode fazer isso:

sys_eval(CONCAT("echo '",myField,"' | base64"));

O primeiro método é conhecido por ser lento. O problema com a segunda, é que a codificação está realmente acontecendo "fora" MySQL, que pode ter codificação de problemas (além de riscos de segurança que você está adicionando com SYS_ * funções).

Infelizmente não existe uma versão UDF compilado (que deve ser mais rápido), nem um suporte nativo no MySQL ( PosgreSQL suporta !).

Parece que a equipe de desenvolvimento do MySQL não estão interessados ??em implementá-lo como esta função já existe em outros idiomas, o que parece bastante tolo para mim.

No entanto, outra implementação personalizada que não requer mesa de apoio:

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

Você deve converter charset após a decodificação: convert(base64_decode(base64_encode('ёлка')) using utf8)

Se você precisa disso para <5,6, eu tropecei através deste UDF que parece funcionar bem:

https://github.com/y-ken/mysql-udf-base64

criar criptografar mesa (varchar nome de usuário (20), varbinary senha (200))

inserção em valores encriptar ( 'Raju', AES_ENCRYPT ( '' Kumar, 'chave')) seleccionar *, fundido (AES_DECRYPT (senha, 'chave') como char (40)) a partir de criptografar onde o utilizador = 'Raju';

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top