sql >> Database teknologi >  >> RDS >> PostgreSQL

Lagring af billeder i bytea-felter i en PostgreSQL-database

TL;DR:

Slet addslashes($data) . Det er overflødigt her.

Dobbelt-escape .. to gange

$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data); 

Du læser dataene ind, undslipper dem, som om det var en streng-literal, og konverterer dem derefter til bytea octal eller hex-escapes. Det kunne aldrig fungere på den måde, selvom pg_escape_bytea var fornuftig, hvilket den ikke er.

PHP's pg_escape_bytea ser ud til at dobbelt-escape outputtet, så det kan indsættes i en streng literal. Dette er utroligt grimt, men der ser ikke ud til at være et alternativ, der ikke gør dette dobbelt-escape, så du kan tilsyneladende ikke bruge parametriserede sætninger til bytea i PHP. Du bør stadig gøre det for alt andet.

I dette tilfælde skal du blot fjerne addslashes linje for data læst ind fra filen er tilstrækkelig.

Testcase, der viser, at pg_escape_bytea double-escapes (og bruger også altid de gamle, ineffektive oktale escapes):

<?php
# oh-the-horror.php
print pg_escape_bytea("Blah binary\x00\x01\x02\x03\x04 blah");
?>

Kør:

php oh-the-horror.php

Resultat:

Blah binary\\000\\001\\002\\003\\004 blah

Ser du de fordoblede skråstreger? Det er fordi det antager, at du vil interpolere det i SQL som en streng, hvilket er ekstremt hukommelsesineffektivt, grimt og en meget dårlig vane. Du ser dog ikke ud til at få noget alternativ.

Det betyder blandt andet, at:

pg_unescape_bytea(pg_escape_bytea("\x01\x02\x03"));

... giver det forkerte resultat , da pg_unescape_bytea er faktisk ikke det modsatte af pg_escape_bytea . Det gør det også umuligt at feed output fra pg_escape_bytea ind i pg_query_params som en parameter skal du interpolere den i.

Afkodning

Hvis du bruger en moderne PostgreSQL, sætter den sandsynligvis bytea_output til hex som standard. Det betyder, at hvis jeg skriver mine data til en bytea feltet og hent det tilbage, vil det se nogenlunde sådan her ud:

craig=> CREATE TABLE byteademo(x bytea);
CREATE TABLE
craig=> INSERT INTO byteademo(x) VALUES ('Blah binary\\000\\001\\002\\003\\004 blah');
INSERT 0 1
craig=> SELECT * FROM byteademo ;
                                     x                                      
----------------------------------------------------------------------------
 \x426c61682062696e6172795c3030305c3030315c3030325c3030335c30303420626c6168
(1 row)

"Øh, hvad", siger du måske? Det er fint, det er bare PostgreSQL's lidt mere kompakte hex-repræsentation af bytea . pg_unescape_bytea vil håndtere det fint og producere de samme rå bytes som output ... hvis du har en moderne PHP og libpq . På ældre versioner vil du få skrald og skal indstille bytea_output for at escape for pg_unescape_bytea at håndtere det.

Hvad du bør gøre i stedet

Brug PDO.

Det har sane(ish) understøttelse af bytea .

$sth = $pdo->prepare('INSERT INTO mytable(somecol, byteacol) VALUES (:somecol, :byteacol)');
$sth->bindParam(':somecol', 'bork bork bork');
$sth->bindParam(':byteacol', $thebytes, PDO::PARAM_LOB);
$sth->execute();

Se:

  • PHP:Store objekter, som har et eksempel på præcis, hvad du vil have;
  • PDOStatement::bindParam
  • hvordan man gemmer serialiseret objekt med navneområde i databasen ved hjælp af pdo php
  • Bind BYTEA til PGSQL PDO-forberedt erklæring i PHP5

Du vil måske også kigge ind på PostgreSQL's lob-understøttelse (stort objekt), som giver en streaming, søgbar grænseflade, der stadig er fuldt transaktionel.

Nu, videre til min sæbeboks

Hvis PHP havde en reel forskel mellem "byte string" og "text string" typer, ville du ikke engang have brug for pg_escape_bytea da databasedriveren kunne gøre det for dig. Intet af denne grimhed ville være påkrævet. Desværre er der ingen separate streng- og bytetyper i PHP.

Brug venligst PDO med parametriserede udsagn så meget som muligt.

Hvor du ikke kan, brug i det mindste pg_query_params og parametriserede udsagn. PHP's addslashes er ikke et alternativ, det er ineffektivt, grimt og forstår ikke databasespecifikke escape-regler. Du skal stadig escape bytea manuelt hvis du ikke bruger PDO af irrelevante historiske årsager, men alt andet skal gå gennem parametriserede udsagn.

For vejledning om pg_query_params :

  • Bobby-tabeller, PHP-sektion.
  • PHP-manualen på pg_query_params


  1. Microsoft Access er IKKE død, og det er VBA heller ikke

  2. NLS_LOWER() Funktion i Oracle

  3. Lagring af filer i SQL Server

  4. Sådan ændres farve og skrifttyper i SQL Server Management Studio (SSMS) - SQL Server / TSQL vejledning del 12