Как восстановить сжатую строку, сохраненную в PostgreSQL ByteA, используя PHP PDO Object?

У меня есть проблема в понимании того, как PHP обрабатывает ByteA с привязкой postgreSQL.

Для целей ведения журнала и архивирования я храню в ByteA файлы столбцов, которые я использую на своем сервере PHP / Apache. Для хранения я сжимаю данные, используя gzencode() а затем я экранирую строку перед сохранением с помощью pg_escape_bytea():

// Compress:
if($compress) {
$data = gzencode($data, 9);
}
// PostgreSQL ByteA Escaping:
$data = pg_escape_bytea($data);

У меня также есть страница, которая позволяет пользователю восстановить ранее обслуживаемые файлы. Но я не могу добиться успеха для сжатого, и я не понимаю, почему:

$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);

/*
$dbCur = $webConn->prepare("SET bytea_output = 'escape';");
$dbCur->execute();
//print_r($dbCur->errorinfo());
*/

$dbCur = $webConn->prepare("SELECT * FROM logs.webservice WHERE Id=?;");
$dbCur->bindParam(1, $id);
$dbCur->execute();
//print_r($dbCur->errorinfo());

$row = $dbCur->fetch(PDO::FETCH_ASSOC);

$data = stream_get_contents($row['binarydata']);
$data = pg_unescape_bytea($data);

if($row['gzip']) {
$data = gzdecode($data);
}

header("Content-type: ".$row['mimetype']."; charset=".$row['charset']);
echo $data;

Я должен использовать объект PDO, все примеры, которые я нашел (даже на сайте PHP), основаны на выделенном API СУБД. Во-вторых, ByteA столбцы возвращаются как ресурсы, тогда мне пришлось использовать stream_getcontents() чтобы получить строку. Когда я храню несжатые файлы, я могу легко восстановить их, что бы я ни использовал или нет SET bytea_output = 'escape'; запрос и / или pg_unescape_bytea() функция. Все комбинации позволяют мне получить файл.

Когда я использую сжатые данные, pg_unescape_bytea() резко съедает почти все мои байты. Во всяком случае, во всех комбинациях, gzdecode() не работает Кажется, в моей двоичной строке отсутствуют или неправильные символы, которые не блокируются в режиме обычного текста. Во всяком случае, эта вещь плохо документирована в Интернете, и я застрял без какой-либо подсказки.

Как мне восстановить сжатую gz-строку, хранящуюся в PostgreSQL ByteA, используя PHP PDO Object?

1

Решение

Решение только проблемы поиска, при условии, что вставка работает

Как только двоичное содержимое попадает в $data со следующим кодом:

$data = stream_get_contents($row['binarydata']);

они уже находятся в необработанном двоичном формате по мере необходимости, поэтому вы не должны декодировать его снова с помощью этого:

$data = pg_unescape_bytea($data);

Просто убери это ложное побег. Причина, по которой вы не замечаете проблему, когда $data имеет только символы ASCII в том, что pg_unescape_bytea преобразует эти символы в себя bytea_output настроен на побег).

Но когда двоичный поток действительно содержит полный диапазон из 256 возможных байтов, например, в gzip-контенте, тогда гарантируется, что pg_unescape_bytea приведет к искаженному результату в этом контексте.

pg_unescape_bytea следует использовать только для строк, которые поступают непосредственно из базы данных как bytea-encoded-as-text.

Как это обычно делается с PDO

На самом деле с PDO мы не должны использовать pg_[un]escape_bytea функции, или даже любые из функций, которые начинаются с pg_* потому что PDO не зависит от базы данных, и его целью является предоставление кода, который работает в разных базах данных.

Вставка должна быть сделана как описано в http://php.net/manual/en/pdo.lobs.php , квалифицируя двоичные параметры с PDO::PARAM_LOB, При этом PDO сам кодирует данные для двоичной передачи, используя соответствующий метод для типа базы данных, к которой он подключен.

При выполнении явного экранирования с pg_escape_bytea()он создает строку, которую PDO может рассматривать как текстовый контент и передавать как таковой. Это способ передачи двоичного кода «за спиной PDO», но в этом нет особого смысла.

Что однозначно не работает, так это смешивание обоих: экранирование (которое создает текст) а также говоря PDO, что это двоичный файл.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector