MYSQLにバイナリで保存した画像を表示する方法

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 4,610

SugiuraY

score 231

お世話になります。
現在、ユーザーからinput="file"で取得したデータをMYSQLにバイナリで保存し、このデータを出力するコードを作成しています。MYSQLにはバイナリデータ(BLOB形式)とMIME(image/jpeg)が格納されており、これをimg.phpで取得して、headerに送信するとともに表示しております。なお、バイナリデータはユーザから formのinput="file"から取得しております。
一方で、output.phpはこれをimg srcに出力し画像を表示させようとしております。

①しかしながらこの結果、HTML上では定番の小さな写真が割れたようなアイコンが表示され意図したimg描画ができていません。どなたか、

なお、バイナリにまだまだ不案内なため、適切か否かはわからないのですが例えば以下のような文字列になっているのですが、一般的な文字化けの状態に見えるのですが、これが原因なのでしょうか?
�a��hfe�+��#�Qn�ǘ8_ڗ]�����[��(˻�#;p�X~_u?J��BrQ��z3��/�\

②また、phpでユーザーから画像とのファイルを取得する場合、ファイルを取得、保存し、それを出力する方法として、より一般的な方法があれば
ご教示いただければ幸いです。

img.php

try {
$pdo = new PDO($dsn, $user, $password,array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`"));
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch (PDOException $e){
 var_dump($e->getMessage());
 }

 try {
 $stmt=$pdo->query("SELECT picture,mime FROM a_inputDB");
$result=$stmt->fetchall(PDO::FETCH_NUM);

}catch(PDOException $e){
echo "失敗しました。" . $e->getMessage();
}

header("Content-type:".$result[0][1]);//$result[0][1]=image/jpeg
echo $result[0][0];//$result[0][0]="���[��(˻�#;p�X~_u....割愛
 ?>

output.php
 <?php
echo '<img src="img.php" />';
?>
input.php
<form  class="form" action="" method="post" enctype="multipart/form-data">
<div>
<label>画像を投稿する</label><br />
<input type="hidden" name="MAX_FILE_SIZE" value="300000" />
<input name="2_picture" type="file" size="35" value="" />
</div>

<?php
// バイナリ
    $fp = fopen($_FILES["2_picture"]["tmp_name"], "rb");
    $imgdat = fread($fp, filesize($_FILES["2_picture"]["tmp_name"]));
    fclose($fp);
    $imgdat = addslashes($imgdat);

    // 拡張子
   $dat = pathinfo($_FILES["2_picture"]["name"]);
   $extension = $dat['extension'];

   // MIME
   if ( $extension == "jpg" || $extension == "jpeg" ) $mime = "image/jpeg";
   else if( $extension == "gif" ) $mime = "image/gif";
   else if ( $extension == "png" ) $mime = "image/png";
?>

$dsn = 'mysql:dbname=XXX;host=XXXX';
$user = 'XXXX';
$password = 'XXXXX';

try {
$pdo = new PDO($dsn, $user, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch (PDOException $e){
 var_dump($e->getMessage());
 }

 try {
$pdo->beginTransaction();
$stmt=$pdo->prepare("INSERT INTO a_inputDB (picture,picturemim)
 VALUES(:picture,:picturemime");
$stmt->bindValue(':picture',$imgdat,PDO::PARAM_STR);
$stmt->bindValue(':picturemime',$mime,PDO::PARAM_STR);
$stmt->execute();
$pdo->commit();

}catch(PDOException $e){
$pdo->rollBack();
echo "失敗しました。" . $e->getMessage();
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

一応、こちらで試してみてアップロード及び表示はできました。
動作したコードを載せます。
違うところといえば、ファイルからバイナリーデータを取得するのにはfile_get_contents()を使用しているのと、MIMETYPEを取得するのにはfinfo_open()/finfo_file()を使用しているところくらいです。

img.php

<?php 
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=image_db;charset=utf8', 'test_user', 'pass');
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $stmt   = $pdo->query("SELECT picture, picturemime FROM a_inputdb");
        $result = $stmt->fetchall(PDO::FETCH_ASSOC);
        header('content-type:'. $result[0]['picturemime']);
        echo $result[0]['picture'];
    }catch(PDOException $e){
        echo "失敗しました。" . $e->getMessage();
    }
?>

upload.php

<?php
if(isset($_FILES["2_picture"]["tmp_name"])){
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=image_db;charset=utf8', 'test_user', 'pass');
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $upFile     = $_FILES["2_picture"]["tmp_name"];
        $upFileData = file_get_contents($upFile);
        $finfo      = finfo_open(FILEINFO_MIME_TYPE);
        $mime_type  = finfo_file($finfo, $upFile);
        $stmt=$pdo->prepare("INSERT INTO a_inputDB(picture, picturemime) values (:img, :mime)");
        $stmt->bindValue(':img', $upFileData, PDO::PARAM_LOB);
        $stmt->bindValue(':mime', $mime_type, PDO::PARAM_STR);
        $stmt->execute();
    }catch(PDOException $e){
        echo "失敗しました。" . $e->getMessage();
    }
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <form method="POST" action="image_upload.php" enctype="multipart/form-data">
            <input type="file" name="2_picture" /><br />
            <input type="submit" value="送信" />
        </form>
    </body>
</html>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/05 20:34

    ご回答ありがとうございます。file_get_contentsでうまく取得し、表示することができました!
    誠にありがとうございます。MIMETYPEはうまく取得できていたので["tmp_name"])をうまく読み込めていなかったのかと思いますが、何れにしても、本当に助かりました。
    最後までお付き合いをいただき、改めて御礼を申し上げます。
    よろしくお願い申し上げます。

    キャンセル

0

1MB以上の画像ファイルってことはないですか?
参考

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/05 12:52

    あ、懸賞の際には念のためブラウザー側のキャッシュをクリアしてから行ってください。

    キャンセル

  • 2017/02/05 12:56

    ご指摘のCHARCTER SETを外してみましたが、やはり依然として画像が適切に表示されない(破れた写真のアイコン)のままのようです。
    MYSQLへの格納のコードについて、念のために上記質問に加筆させていただきます。

    キャンセル

  • 2017/02/05 13:05

    はい、casheをクリアして実行をしてみましたが、同様の結果です。
    よろしくお願い申し上げます。

    キャンセル

0

画像保存時のバイナリーデータのところでPDO::PARAM_STRを設定してますが、PDO::PARAM_LOBとすべきではないでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/05 14:40

    ご指摘の点は、おっしゃるとおりでした。修正し、casheもクリアしましたが、表示はされません。。MYSQL側のエンゴード等の問題なのか、、(全てutf-8にはしておりますが)。。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.22%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる