このエントリーをはてなブックマークに追加


PHPによるバイナリデータをbytea型に保存と取得する方法

PHPスクリプトを使ってバイナリ列データ型(bytea)へのバイナリーデータの挿入と取得方法を以下に記します。

関連記事

外部参考記事

使用した環境

使用した環境は以下の通りです。

  • OS
    sakura@ubuntu:~$ lsb_release -a
    No LSB modules are available.
    Distributor ID: Ubuntu
    Description: Ubuntu 12.04.3 LTS
    Release:  12.04
    Codename:    precise
  • PostgreSQL
    sakura@ubuntu:~$ sudo -i -u postgres
    postgres@ubuntu:~$ psql -c "select version();"
                  version
    ------------------------------------------------------------------------------------------------------
     PostgreSQL 9.1.11 on i686-pc-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 32-bit
    (1 row)
  • PHP
    postgres@ubuntu:~$ php -version
    PHP 5.3.10-1ubuntu3.9 with Suhosin-Patch (cli) (built: Dec 12 2013 04:24:43)
    Copyright (c) 1997-2012 The PHP Group
    Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

PHP向けPostgreSQLモジュールについて

以下のようなエラーが出る場合は、PHP用のPostgreSQL用のモジュールがインストールされていません。

PHP Fatal error:  Call to undefined function pg_connect() ...

Ubuntuの場合は、以下のコマンドでインストールしてください。

sudo apt-get install php5-pgsql

他のOS環境の場合は、php向けPostgreSQLのモジュールをインストールしてください。

画像データを投入するPHPスクリプト

Let's postgres - PHPでのSQLインジェクション対策 - エスケープ・クォート編: pg_escape_****を参考にhex書式でPHPサンプルスクリプトを紹介します。

以下のようなデータベースおよびテーブルを作成しました。

postgres@ubuntu:~$ createdb img_db
postgres@ubuntu:~$ psql img_db -c "create table t1 (no int, img bytea);"
CREATE TABLE

画像データをinsertしてみる

<?php
  $DBNAME = 'img_db';

  if ($argc != 3) {
    echo "Usage: php $argv[0] <number> <image filename>\n";
    exit(1);
  }

  if (!is_numeric($argv[1])) {
    echo $argv[1] . " is not numeric.\n";
    exit(1);
  }

  if (!file_exists($argv[2])) {
    echo $argv[2] . " file not found.\n";
    exit(1);
  }

  $no = $argv[1];
  $img_filename = $argv[2];

  $img_data = file_get_contents($img_filename);

  $dbconn = pg_connect("dbname=$DBNAME");
  $sql = 'INSERT INTO t1 VALUES(' .
         $no . ',' .
         '\'' . pg_escape_string($dbconn,'\x' . bin2hex($img_data)) . '\'' .
         ')';
  $res = pg_query($dbconn, $sql);
  pg_close($dbconn);
?>

以下の画像データを用意しました。

sakura-it.png

以下のコマンドでPostgreSQLに挿入してみます。

php ins_img.php 1 sakura-it.png

実際に実行したときの出力です。

postgres@ubuntu:~$ php ins_img.php 1 sakura-it.png
postgres@ubuntu:~$
postgres@ubuntu:~$ psql img_db -c 'select count(*) from t1;'
 count
-------
  1
(1 row)

画像データと取り出す

上記の手順でPostgreSQLに挿入した画像データ(PNG)を取り出してみます。

<?php
  $DBNAME = 'img_db';

  if ($argc != 2) {
    echo "Usage: php $argv[0] <number> > filename\n";
    exit(1);
  }

  if (!is_numeric($argv[1])) {
    echo $argv[1] . " is not numeric.\n";
    exit(1);
  }

  $no = $argv[1];

  $dbconn = pg_connect("dbname=$DBNAME");
  $sql = 'SELECT img FROM t1 WHERE ' .
         'no = ' . $no;
  $res = pg_query($dbconn, $sql);
  echo pg_unescape_bytea(pg_fetch_result($res, 'img'));
  pg_close($dbconn);
?>

以下のコマンドでPostgreSQLから上記で挿入した画像データを取り出してみます。

php get_img.php 番号(カラムnoの値) > 出力ファイル名

実際に実行したときの出力です。

postgres@ubuntu:~$ php get_img.php 1 > get_img.png
postgres@ubuntu:~$ diff sakura-it.png get_img.png
postgres@ubuntu:~$ echo $?
0

diffにより元データ(sakura-it.png)とget_img.phpスクリプトで取り出したget_img.pngを比較しました。
差異がないのが確認できます。

以上、bytea型に画像データを挿入と取得例でした。
画像データに限らず、MS Officeの文書ファイルなどバイナリデータであれば同様に動作します。


添付ファイル: fileget_img.php 623件 [詳細] fileins_img.php 765件 [詳細] filesakura-it.png 673件 [詳細] filesakura-it.zip 475件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-03-20 (金) 22:08:00