TL;DR:
Изтрийте addslashes($data)
. Тук е излишно.
Двойно избягване .. два пъти
$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data);
Вие четете данните, избягвате ги, сякаш са низови литерал, след което ги преобразувате в байт осмични или шестнадесетични екрани. Никога не би могло да работи по този начин, дори ако pg_escape_bytea
беше разумен, което не е.
pg_escape_bytea
на PHP изглежда двойно избягване изхода, така че да може да бъде вмъкнат в низов литерал. Това е невероятно грозно, но изглежда няма алтернатива, която да не прави това двойно избягване, така че изглежда не можете да използвате параметризирани изрази за bytea в PHP. Все пак трябва да го правите за всичко останало.
В този случай просто премахване на addslashes
ред за прочетените данни от файла е достатъчен.
Тестов случай, показващ, че pg_escape_bytea
двойно извеждане (и винаги използва и старите, неефективни осмични екрани):
<?php
# oh-the-horror.php
print pg_escape_bytea("Blah binary\x00\x01\x02\x03\x04 blah");
?>
Пусни:
php oh-the-horror.php
Резултат:
Blah binary\\000\\001\\002\\003\\004 blah
Виждате ли удвоените обратни наклонени черти? Това е така, защото се предполага, че ще го интерполирате в SQL като низ, което е изключително неефективно за паметта, грозно и много лош навик. Изглежда обаче нямаш алтернатива.
Наред с други неща, това означава, че:
pg_unescape_bytea(pg_escape_bytea("\x01\x02\x03"));
... дава грешен резултат , тъй като pg_unescape_bytea
всъщност не е обратното на pg_escape_bytea
. Освен това прави невъзможно подаването на изхода на pg_escape_bytea
в pg_query_params
като параметър, трябва да го интерполирате.
Декодиране
Ако използвате модерен PostgreSQL, той вероятно задава bytea_output
към hex
по подразбиране. Това означава, че ако запиша данните си в bytea
поле, след което го извлечете обратно, ще изглежда така:
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)
„Хм, какво“, бихте казали? Всичко е наред, просто е малко по-компактното шестнадесетично представяне на PostgreSQL на bytea
. pg_unescape_bytea
ще се справи добре и ще произведе същите сурови байтове като изхода ... ако имате модерен PHP и libpq
. В по-старите версии ще получите боклук и ще трябва да зададете bytea_output
за escape
за pg_unescape_bytea
да се справя.
Какво трябва да направите вместо това
Използвайте PDO.
Той има разумна (ish) поддръжка за 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();
Вижте:
- PHP:Големи обекти, който има пример за точно това, което искате;
- PDOStatement::bindParam
- как да съхранявате сериализиран обект с пространство от имена в база данни с помощта на pdo php
- Свържете BYTEA към PGSQL PDO подготвена декларация в PHP5
Може също да искате да разгледате поддръжката за лоб (голям обект) на PostgreSQL, която осигурява поточно, търсещ интерфейс, който все още е напълно транзакционен.
Сега към моята кутия за сапун
Ако PHP имаше истинска разлика между типовете "байтов низ" и "текстов низ", дори нямаше да се нуждаете от pg_escape_bytea
тъй като драйверът на базата данни може да го направи вместо вас. Нищо от тази грозота няма да се изисква. За съжаление, в PHP няма отделни типове низове и байтове.
Моля, използвайте PDO с параметризирани изрази колкото е възможно повече.
Където не можете, използвайте поне pg_query_params
и параметризирани изявления. addslashes
на PHP не е алтернатива, той е неефективен, грозен и не разбира специфичните за базата данни правила за избягване. Все още трябва ръчно да избягвате bytea
ако не използвате PDO по гадни исторически причини, но всичко останало трябва да премине през параметризирани оператори.
За насоки относно pg_query_params
:
- Таблици Боби, PHP секция.
- Ръководството за PHP за
pg_query_params