Conforme PHP/PDO/MySQL :inserir em MEDIUMBLOB armazena dados incorretos , tente usar a seguinte linha para construir seu objeto PDO:
$dbh = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES latin1 COLLATE latin1_general_ci"));
Explicação
Eu acho que existem, como Ben M observa na pergunta vinculada, duas decisões ruins de design em ação aqui.
Existe esse conceito de um conjunto de caracteres de conexão. A ideia é que o texto SQL possa estar em qualquer conjunto de caracteres e seja convertido na recuperação pelo servidor SQL.
Isso não funciona tão bem com dados binários, pois não é texto e, portanto, não deve, por definição, estar em nenhum conjunto de caracteres, mas ainda é transferido usando literais de string .
Esse problema pode ser contornado citando dados BLOB durante a transferência (usando as funções BASE64_* ou escape hexadecimal ) e, de fato, é isso que muitas pessoas estão fazendo.
A segunda decisão de design é em PDO/PHP:PDO não faz nenhuma conversão de charset (não pode, porque strings em PHP são inerentemente charset-agnostic) então PHP é a única (ou uma das poucas linguagens) onde a escolha de o conjunto de caracteres de transferência SQL é realmente importante porque precisa corresponder à codificação em que as strings de entrada estão realmente.
Em outras linguagens, o charset de transferência só precisa ser expressivo o suficiente para abranger quaisquer caracteres que possam ser usados em strings. No mundo de emojis de hoje, isso provavelmente só é garantido por conjuntos de caracteres unicode (utf-8 e similares). No entanto, nenhuma delas é segura para binários (na medida em que nem toda combinação possível de bytes produz uma string válida), mesmo que pudéssemos contornar o problema do PHP, ainda ficaríamos com o problema #1.
Em um mundo ideal, os comandos SQL estariam sempre no charset ASCII durante a transferência e cada valor de string teria um argumento charset, do qual “binary” poderia ser um valor possível, fornecido com ele. O MySQL na verdade tem uma construção para strings, que ele chama de “introdutor”. “_binary”, no entanto, não parece ser um valor válido.
Essas informações do conjunto de caracteres seriam usadas pela outra extremidade para converter o valor da string em seu conjunto de caracteres nativo (a coluna para transferências de cliente para servidor ou o conjunto de caracteres de string da linguagem de programação para transferências de servidor para cliente).
Dessa forma, a única coisa que teria que ser escapada nos valores BLOB seria o delimitador de string (
"
ou '
).