PHPの mysqli から画像などをバイナリ保存する正しいやり方

MySQLでこういうデータを保存したい場合、

  • PNGとかJPEGとかの画像
  • 圧縮されたデータ
  • その他バイナリなど

こういうバイナリ保存の方法は難しくありません。

ただいくつか注意すべきことも多いです。

そこで PHPの mysqli からバイナリ保存する方法 をまとめました。

画像を直にMySQL保存するケースでの話

手順1.まず画像バイナリを保存するテーブルを作る

例えばこんなテーブルを作ったとします。

▼ 例えば画像名とデータを記録するテーブル的な

画像データそのものは data  カラムに保存するとしましょう。

そのとき大事なのは、型を次の4ついずれか にすること

型名 最大容量(bytes) 補足
TINYBLOB 255 どういう用途で使うんだろ
BLOB(M) 65535 約64KB。長さをMで指定可
MEDIUMBLOB 16777215 約15MB。そこそこ大きい
LONGBLOB 4294967295 約4GB。動画でもギリ保存可能

画像とかなら MEDIUMBLOB  で十分なはず

4GB容量の LONGBLOB  もあるけど、さすがに必要ないですね。そもそもそんな大容量データは ファイルとして保存 した方がベストです。

もし LONGBLOB  で考えているなら、テーブル設定の見直しが必要かもしれません。

手順2.PHPの mysqli から画像データをinsertしてみる

今作った画像テーブル

そこに次のレコードを挿入したいとしましょう。

  • idカラム : オートインクリメント
  • nameカラム : image.jpeg
  • dataカラム : 10KBほどの画像データ

 

その場合、以下のPHPを書けば画像データごとinsert可能です。

▼ 実際のPHPコード例

大事なポイントは次の3つ

  • プリペアステートメントを使う(当然)
    バイナリを渡すので mysqli::prepare  を使う。当然ながらMySQLインジェクションを防ぐためでもある
  • BLOB型のバインド変数は null にする
    なぜか bind_param ではバイナリデータを直に渡せない。そのため $DUMMY_NULL  というダミー変数を作り、セットしている。
  • バイナリは send_long_data から送信
    肝心のバイナリデータは send_long_data( 0, $jpeg_data );  のように送信。1つめの引数がパラメーターのインデックス位置、2つめがデータそのもの

上コードみたいに send_long_data  を使うのが必須みたいです。

てっきり bind_params  から渡せると勘違いしていた・・・

安全にバイナリデータを渡すなら、こっちの方を使う方がいいみたいですね。

蛇足.バイナリをMySQLに直保存する是非について...

補足ではなく蛇足

バイナリをMySQLに直接保存する是非についてです

 

この話題については 賛否両論いろいろあります。

▼ バイナリ保存に肯定的な意見

  • 小さいデータだったら別にいいんじゃない?
  • MySQLに保存した方が便利な場合もあるし、、、

▼ バイナリ保存に否定的な意見

  • 直接バイナリ保存とかありえない!
  • 普通にファイルで保存すれば、、、?

まあ絶対的な答えはないですね。

実際 LONGBLOB  を使えば、バイナリでも4GBまで保存できる訳で・・・

仕様的にバイナリ保存がダメな理由はないです。

 

あとバイナリ保存も次の場合は許されるかな、と思ってます。

  • 容量が決まっている場合
    => たとえば最大1KBまでとか制限があるとか
  • MySQL保存の方が便利な場合
    => 条件を指定いして絞り込みとかしたいケース

でも画像に関しては、どちらかといえばファイル保存ですね。

CMS(WordPressなど)でもデータベースに画像保存されてないし、
そもそもデータベース容量は 500MB とかの制限があるサーバーも多いです。

だから容量固定以外はファイル保存が基本かなという感じ。

まあケースバイケースで判断すればいいのかなと思います。

ここまでのまとめ

PHPで mysqli でバイナリ保存するのは少し面倒です。

でもやり方さえ間違えなければ、意外と簡単だと思いました。

もしコード的な誤りがあるならご指摘ください。ではでは($・・)/~~~

PHP

Commentsこの記事についたコメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください