質問: * 概要 CentOS5 32bit の環境をバージョンアップするためにCentOS6 64bitへ移行しようとしております。 PostgreSQLのデータをdumpallして64bitの新環境にデータを移したのですが、 その中のデータに画像をbytea型というバイナリデータにして格納されているカラムがあり、 中身自体は64bit仕様に書き換えられているように見えるのですが、ブラウザ表示でエラーとなります。 さらに、64bit環境で新規に登録したデータについても同様のエラーが発生しており、それについても対処法がわからず困っております。 * 質問内容 後述の詳細欄にて対処したことや、32bitが関係ないように思える64bit内での動きを書いておりますが、質問内容としては以下のことがメインです。 > > 32bitから64bitのOSへ移行したときのPostgres内bytea型のデータは、dumpallしてそのままphpで扱えるデータなのか。使えない場合はどうしたら64bit版のデータに変換できるのか。 > > > * 詳細 ■アプリについて ・webサーバ:apacheとphp ・DBサーバ:postgres ・OS:どちらもCentOSで今回5の32bitから6の64bitにアップグレードする となっており、ブラウザ上で操作するとphpからpostgresを操作してデータをとり、表示するといった構成です。 ■bytea型でpostgreに保存されているデータについて ・画像データ ・画像に付随する情報データ の2種類が別カラムで保存されている状態です。32bitのOSのときにphpPgAdminにて確認したデータ形式は32bit仕様のものでしたが、dumpall後に64bitのOSに移したときには中身が変わっていて、一見すると64bit仕様の形式になっているように見えます。(すみません、調査してもこれ以上のことはよくわかりませんでした。) ■エラーについて ブラウザ上でbytea型で保存されている画像を表示させるときに下記のエラーがでます。 ``` Warning : pack() [function.pack]: Type H:illegal hex digit x in ○○○←対象phlファイル名 ``` ■行った対処法 64bit環境に移行した後で、新規に登録した画像データについても上記エラーが発生することがわかり、エラーにて表示されているファイルの場所から調査しました。 すると、既に別のプログラムでデコード処理は行われていたのですが、pack()関数だとバイナリデータの0~f以外の文字列を変換できないためエラーが発生することまでわかりました。 その回避方法として、pack()関数の前にpg_unescape_byea()関数を使用してバイナリデータをアンエスケープしたのですが、ローカル検証機(32bitデータは入っていない)ではこの対処法でエラーが消えたにもかかわらず、本環境ではエラーが消えませんでした。 ■上記対処法に対して調査した結果 ローカル環境ではbytea型の中身は¥xから始まる文字列であるのに対し、本環境では16進数で表示されていることがわかりました。しかし、このデータをvar_dump()で表示した場合は¥xで始まる文字列で表示されていて、正直どういったことが起きているのかよくわかりません。 ■行った対処法2 DBのデータ型をbytea型からtext型に変更したところ、phpのコードの変更なく、pack()関数だけでうまくいきました。しかし、データ型を変更すると以前のデータを表示できなくなる可能性があるため、あくまで最悪の手段としてできればこの方法は使いたくありません。 以上です。 少しまとまりが悪い質問となってしまい申し訳ございませんが、何卒ご教示頂けませんでしょうか。 --- 追記1 postgresqlのバージョンは 移行前:8.3 移行後:9.2 となっております。
回答: 同じ環境とPHPが揃わなかったのでご参考としてください。 > > 32bitから64bitのOSへ移行したときのPostgres内bytea型のデータは、dumpallしてそのままphpで扱えるデータなのか。使えない場合はどうしたら64bit版のデータに変換できるのか。 > > > に関してのみですが、下記の環境ではできました。但しdumpallでなくpg_dumpにてテーブル指定して行いましたので、異なるかもしれません。 CentOS 5.3(32bit) Postgres 8.3.8 CentOS 6.8(64bit) Postgres 9.3.6 (1)32ビットサーバでjpegファイルをPHPで取り込み (2)pg_dumpでダンプファイルを作成 (3)64ビットサーバで上記ファイルをpsqlで取り込み (4)phpでブラウザでjpegイメージを表示 つたないテストPHPですが・・・ ``` $conn = pg_connect( 'host=127.0.0.1 port=5432 dbname=hogedb user=hoge' ); if( $conn == false ) exit; $sql = "SELECT ENCODE( byte_data::bytea, 'escape' ) byte_data FROM tst_image"; $res = pg_query( $sql ); if( $res == false ) exit; $data = pg_fetch_object( $res ); if( $data == false ) exit; //DB切断 pg_free_result( $res ); pg_close( $conn ); //画像の情報を取得する $img = base64_encode( pg_unescape_bytea( $data->byte_data ) ); $scheme = 'data:application/octet-stream;base64,'; $size = getimagesize( $scheme . $img ); if( $size == false ) exit; //バイナリに変換し、ブラウザに送信する header( 'Content-type: ' . $size['mime'] ); echo pg_unescape_bytea( $data->byte_data ); exit; ```