1

PHP が postgreSQL バインディングで ByteA を処理する方法を理解するのに問題があります。

ログとアーカイブの目的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 Web サイトでも) は、専用の DBMS API に基づいています。次に、ByteA列がリソースとして返されるstream_getcontents()ため、文字列を取得するために使用する必要がありました。SET bytea_output = 'escape';圧縮されていないファイルを保存すると、クエリや関数を使用するかどうかに関係なく、簡単に復元できpg_unescape_bytea()ます。すべての組み合わせでファイルを取得できます。

圧縮データを使用すると、pg_unescape_bytea()ほぼすべてのバイトが劇的に消費されます。とにかく、すべての組み合わせでgzdecode()機能しません。プレーン テキスト モードでブロックされないバイナリ文字列に文字がないか間違っているようです。とにかく、このことはインターネット上で十分に文書化されておらず、何の手がかりもなく立ち往生しています.

PHP PDO オブジェクトを使用して PostgreSQL ByteA に保存されている gzcompressed 文字列を復元するにはどうすればよいですか?

4

1 に答える 1

1

挿入が機能すると仮定して、取得の問題のみを解決する

$dataバイナリ コンテンツが次のコードに入ると、次のようになります。

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

それらは必要に応じてすでに生のバイナリ形式になっているため、これを使用して再度デコードしないでください。

$data = pg_unescape_bytea($data);

その偽のエスケープ解除を削除するだけです。$dataが ASCII 文字のみ の場合に問題に気付かない理由は、pg_unescape_byteaこれらの文字を自分自身に変換するためです (bytea_outputエスケープするように設定されている場合)。

しかし、gzip されたコンテンツのように、バイナリ ストリームに 256 バイトの全範囲が実際に含まれているpg_unescape_bytea場合、そのコンテキストで破損した結果が生成されることが保証されます。

pg_unescape_byteabytea-encoded-as-text としてデータベースから直接取得される文字列でのみ使用する必要があります。

PDO での通常の方法

実際、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 にバイナリであることを伝えることの両方を混在させることです。

于 2016-10-13T18:29:57.937 に答える