2016-10-13 12 views
1

У меня возникла проблема в понимании того, как PHP обрабатывает ByteA с привязкой postgreSQL.Как восстановить gz сжатую строку, хранящуюся в PostgreSQL ByteA, используя PHP PDO Object?

Для ведения журнала и архивирования я храню в файлах столбцов ByteA, которые я обслуживаю с помощью моего PHP/Apache Server. Для хранения, сжать данные, используя 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 возможных байтов, например, в gzipped-контенте, то гарантируется, что pg_unescape_bytea приведет к поврежденному результату в этом контексте.

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

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

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

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

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

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

+0

Я действительно смущен об этом. Я вижу, что он связан с кодировкой. Но я не могу заставить его работать. Я не могу хранить gz сжатые данные в ByteA, не используя pg_escpae_bytea, и это может быть проблемой. Что мне не хватает? – jlandercy

+0

Вставка gzcompressed без pg_escape_bytea дает мне ERROR: неверная последовательность байтов для кодирования «UTF8»: 0x8b. Когда я использую fucntion, возвращаемые данные возвращают что-то другое, что я вставил. – jlandercy

+0

Эта страница http://sickel.net/blogg/?p=1365 предоставляет решение, но она работает контрпродуктивно и точно соответствует тому, как я хочу работать. Я хочу хранить двоичные данные (и я не могу это сделать без изменения формата gzip) вместо шестнадцатеричного строкового представления двоичных данных. – jlandercy

 Смежные вопросы

  • Нет связанных вопросов^_^