Sibainu Relax Room

柴犬と過ごす

独習PHP 画像データが表示できない

きっりとした顔になって励ましてくれる柴犬です。

概要

独習PHPを順調に読み進めている中で、実行できなかったコードがあったので調べてみました。

WEBで調べても分からなかったので我流の解決方法です。

これで、丸1日かなり疲れました。

一応解決しましたが、気に入らないところがありますので気に留めて今後もっといい解決方法が分かればまた投稿します。

想定していないエラー

独習PHPを順調に読み進め、リスト9.32 のコードを実行してみました。

もちろん、画像データも リスト9.36 のコードを実行して MySQL に登録したものを使いました。

copy

<?php
require_once '../DbManager.php';

try {
  $db = getDb();
  $stt = $db->prepare('SELECT * FROM photo WHERE id = ?');
  $stt->bindValue(1, $_GET['id'] ?: 1);
  $stt->execute();
  $stt->bindColumn('type', $type, PDO::PARAM_STR);
  $stt->bindColumn('data', $data, PDO::PARAM_LOB);
  if ($stt->fetch(PDO::FETCH_BOUND)) {
    header("Content-Type: {$type}");
    print $data;
  } else {
    print '該当するデータがありません。';
  }
} catch(PDOException $e) {
  die("エラーメッセージ:{$e->getMessage()}");
}

しかし、エラー処理に掛からない次の画像のエラーが発生しました。

原因を調べるため試行錯誤した結果、

$stt->bindValue(1, $_GET['id'] ?: 1);

print $data;

に原因があることが分かりました。

変更後

原因の行をそれぞれ次のようにしてみました。

$stt->bindValue(1, 1);
print stream_get_contents(fpassthru($data), -1, 3);

2つ目は、調べている中でBOMが付いている場合があるということが分かり、BOM分3バイトオフセットしてみました。

fpassthrustream_get_contents は公式HPによると次のようです。

https://www.php.net/manual/ja/function.fpassthru
ファイルポインタ上に残っているすべてのデータを出力する

https://www.php.net/manual/ja/function.stream-get-contents.php
残りのストリームを文字列に読み込む
3はオフセット量で-1 は残り全部ということらしいです。

copy

<?php
require_once '../DbManager.php';

try {
  $db = getDb();
  $stt = $db->prepare('select * from photo where id = ?');
  $stt->bindValue(1, 1);
  $stt->execute();
  $stt->bindColumn('type', $type, PDO::PARAM_STR);
  $stt->bindColumn('data', $data, PDO::PARAM_LOB);
  if ($stt->fetch(PDO::FETCH_BOUND)) {
    header("Content-Type: {$type}");
    print stream_get_contents(fpassthru($data), -1, 3);
  } else {
    print '該当するデータがありません。';
  }
} catch (PDOException $e) {
  die("エラーメッセージ:{$e->getMessage()}");
}

ブラウザから開いて表示できました。

柴犬もほっとしていることでしょう。