Mysql
 sql >> Database >  >> RDS >> Mysql

Salvataggio di file come BLOB nel database ajax php pdo

Secondo PHP/PDO/MySQL :l'inserimento in MEDIUMBLOB memorizza dati errati , prova a utilizzare la seguente riga per costruire il tuo oggetto PDO:

$dbh = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES latin1 COLLATE latin1_general_ci"));

Spiegazione

Penso che, come fa notare Ben M nella domanda collegata, ci siano due pessime decisioni di progettazione al lavoro qui.

C'è questo concetto di un set di caratteri di connessione. L'idea è che il testo SQL può essere in qualsiasi set di caratteri e viene quindi convertito al recupero da parte del server SQL.

Questo non funziona molto bene con i dati binari in quanto non è testo e, quindi, non deve, per definizione, essere in nessun set di caratteri, ma viene comunque trasferito utilizzando stringhe letterali .

Questo problema può essere risolto citando i dati BLOB durante il trasferimento (utilizzando le funzioni BASE64_* o escaping esadecimale ) e, in effetti, è quello che stanno facendo molte persone.

La seconda decisione di progettazione è in PDO/PHP:PDO non esegue alcuna conversione di charset (non può, perché le stringhe in PHP sono intrinsecamente indipendenti dai charset), quindi PHP è l'unico (o uno dei pochi linguaggi) in cui la scelta di il charset di trasferimento SQL è in realtà importante perché deve corrispondere alla codifica in cui si trovano effettivamente le stringhe di input.

In altre lingue, il set di caratteri di trasferimento deve essere sufficientemente espressivo da comprendere tutti i caratteri che potrebbero essere utilizzati nelle stringhe. Nel mondo odierno degli emoji, molto probabilmente è garantito solo da set di caratteri Unicode (utf-8 e simili). Tuttavia, nessuno di questi è sicuro per i binari (in quanto non tutte le possibili combinazioni di byte producono una stringa valida), quindi anche se potessimo aggirare il problema di PHP, rimarremmo comunque con il problema n. 1.

In un mondo ideale, i comandi SQL sarebbero sempre nel set di caratteri ASCII durante il trasferimento e ogni valore di stringa avrebbe un argomento di set di caratteri, di cui "binario" potrebbe essere un possibile valore, fornito con esso. MySQL ha effettivamente un tale costrutto per le stringhe, che chiama "introduttore". “_binary”, tuttavia, non sembra essere un valore valido.

Queste informazioni sul set di caratteri verrebbero quindi utilizzate dall'altra estremità per convertire il valore della stringa nel set di caratteri nativo (la colonna per i trasferimenti da client a server o il set di caratteri di stringa del linguaggio di programmazione per i trasferimenti da server a client).

In questo modo, l'unica cosa di cui è necessario eseguire l'escape nei valori BLOB sarebbe il delimitatore di stringa (" o ' ).