質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

89.20%

【php+mysql】画像をアップロードしてデータベースにサムネイル画像と共に保存して、それを表示したい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 2,903

awazon042

score 13

現在下記の様に表示していますが、サムネイルをクリックした時に何も表示されません。
それ以外はしっかり機能しています。
画像はデータベースに直接保存しています。
若輩者ですが、ご教授いただければ幸いです

ソースコード

<?php
/* HTML特殊文字をエスケープする関数 */
function h($str) {
    return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}
// XHTMLとしてブラウザに認識させる
// (IE8以下はサポート対象外w)
header('Content-Type: text/html; charset=UTF-8');
$cast_id = h($_GET['id']);
$date = (new DateTime('now', new DateTimeZone('Asia/Tokyo')))->format('YmdHis');
$name = h($cast_id . "-" . $date);
try {

    $dsn = 'mysql:dbname=A_datebase;host=A.ne.jp;charset=utf8';
    $user = 'A;
    $password = 'A1234';
    $options = array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // SQL実行失敗時にも例外を投げるようにする
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // デフォルトフェッチモードを連想配列に設定
    );
    // DB接続してPDOインスタンス生成
    $pdo = new PDO($dsn, $user, $password, $options);
    /* アップロードがあったとき */
    if (isset($_FILES['upfile']['error']) && is_int($_FILES['upfile']['error'])) {

        // バッファリングを開始
        ob_start();

        try {

            // $_FILES['upfile']['error'] の値を確認
            switch ($_FILES['upfile']['error']) {
                case UPLOAD_ERR_OK: // OK
                    break;
                case UPLOAD_ERR_NO_FILE:   // ファイル未選択
                    throw new RuntimeException('ファイルが選択されていません', 400);
                case UPLOAD_ERR_INI_SIZE:  // php.ini定義の最大サイズ超過
                case UPLOAD_ERR_FORM_SIZE: // フォーム定義の最大サイズ超過
                    throw new RuntimeException('ファイルサイズが大きすぎます', 400);
                default:
                    throw new RuntimeException('その他のエラーが発生しました', 500);
            }

            // $_FILES['upfile']['mime']の値はブラウザ側で偽装可能なので
            // MIMEタイプを自前でチェックする
            if (!$info = @getimagesize($_FILES['upfile']['tmp_name'])) {
                throw new RuntimeException('有効な画像ファイルを指定してください', 400);
            }
            if (!in_array($info[2], [IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG], true)) {
                throw new RuntimeException('未対応の画像形式です', 400);
            }

            // サムネイルをバッファに出力
            $create = str_replace('/', 'createfrom', $info['mime']);
            $output = str_replace('/', '', $info['mime']);
            if ($info[0] >= $info[1]) {
                $dst_w = 500;
                $dst_h = ceil(500 * $info[1] / max($info[0], 1));
            } else {
                $dst_w = ceil(500 * $info[0] / max($info[1], 1));
                $dst_h = 500;
            }
            if (!$src = @$create($_FILES['upfile']['tmp_name'])) {
                throw new RuntimeException('画像リソースの生成に失敗しました', 500);
            }
            $dst = imagecreatetruecolor($dst_w, $dst_h);
            imagecopyresampled($dst, $src, 0, 0, 0, 0, $dst_w, $dst_h, $info[0], $info[1]);
            $output($dst);
            imagedestroy($src);
            imagedestroy($dst);

            // INSERT処理

            $stmt = $pdo->prepare('INSERT INTO image(name,cast_id,type,raw_data,thumb_data,date) VALUES(?,?,?,?,?,?)');
            $stmt->execute([
                $name,
                $cast_id,
                $info[2],
                file_get_contents($_FILES['upfile']['tmp_name']),
                ob_get_clean(), // バッファからデータを取得してクリア
                (new DateTime('now', new DateTimeZone('Asia/Tokyo')))->format('Y-m-d H:i:s'),
            ]);

            $msgs[] = ['green', 'ファイルは正常にアップロードされました'];
        } catch (RuntimeException $e) {

            while (ob_get_level()) {
                ob_end_clean(); // バッファをクリア
            }
            http_response_code($e instanceof PDOException ? 500 : $e->getCode());
            $msgs[] = ['red', $e->getMessage()];
        }

        /* ID指定があったとき */
    } elseif (isset($_GET['id'])) {


        try {

            $stmt = $pdo->prepare('SELECT type, raw_data FROM image WHERE no = ? LIMIT 1');
            $stmt->bindValue(1, $_GET['id'], PDO::PARAM_INT);
            $stmt->execute();
            if (!$row = $stmt->fetch()) {
                throw new RuntimeException('該当する画像は存在しません', 404);
            }
            header('X-Content-Type-Options: nosniff');
            header('Content-Type: ' . image_type_to_mime_type($row['type']));
            echo $row['raw_data'];
            exit;
        } catch (RuntimeException $e) {

            http_response_code($e instanceof PDOException ? 500 : $e->getCode());
            $msgs[] = ['red', $e->getMessage()];
        }
    }

    // サムネイル一覧取得
    $rows = $pdo->prepare("SELECT * FROM image WHERE cast_id=? ORDER BY date DESC");
    $rows->execute(array($cast_id));
} catch (PDOException $e) {

    http_response_code(500);
    $msgs[] = ['red', $e->getMessage()];
}
?>
<?php if (!empty($rows)): ?>
                        <legend>サムネイル一覧(クリックすると原寸大表示)</legend>
                        <div class="thumnail_table">

                            <?php foreach ($rows as $i => $row): ?>
                                <table class="cast_photo_table">
                                    <tbody>
                                        <tr>
                                            <td colspan="2">
                                                <?=
                                                sprintf(
                                                        '<a href="?no=%d"><img src="data:%s;base64,%s" alt="%s" width="200px"/></a>', $row['no'], image_type_to_mime_type($row['type']), base64_encode($row['thumb_data']), h($row['name'])
                                                )
                                                ?></td>
                                        </tr>
                                        <tr><th>ファイル名:</th><td><?= h($row['name']) ?></td></tr>
                                        <tr><th>日付:</th><td><?= h($row['date']) ?></td></tr>
                                        <tr><td colspan="2"><span class="delete"><a href="delete_photo.php?no=<?= h($row['no']) ?>">削除する</a></span></td><tr>
                                    </tbody>
                                </table>
                            <?php endforeach; ?>
                        </div>
                    <?php endif; ?>

補足情報(言語/FW/ツール等のバージョンなど)

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • usk

    2016/01/27 15:53 編集

    追加・修正依頼を記載しましたが、表示内容が汚くなったので、コメント欄にて再掲載します。

    キャンセル

回答 2

checkベストアンサー

0

(追加・修正依頼です)

それ以外はしっかり機能しています。 

サムネイルが表示されていないということは、どこかに問題が隠れているはずです。
何がしっかりと機能しているか、もう少し明確にお伝えいただけないでしょうか。

  • DB にデータは保存されているかどうか
  • ID を元にDBからデータを取得するところは正しく動いているかどうか
    (PHP上で、IDからデータが取得できたかどうか)
  • HTML に DB から取得した画像データ base64 エンコード済みの文字列は設定されているかどうか
  • base64エンコードされた画像のデータはブラウザのURLに入力した場合、画像が表示されるかどうか

このあたりを確認してみて、もう少し問題内容を詳細化することは可能でしょうか。

参考URL
http://blue-ham-cake1024.hatenablog.com/entry/2013/02/09/Base64%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89%E3%81%95%E3%82%8C%E3%81%9F%E7%94%BB%E5%83%8F%E3%82%92%E3%83%87%E3%82%B3%E3%83%BC%E3%83%89%E3%81%97%E3%81%A6%E9%96%B2%E8%A6%A7%E3%81%99

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/01/27 16:09

    すいません、質問の文章がおかしかったのかもしれません。
    サムネイルは表示されているのですが、サムネイルをクリックした後の挙動がおかしいということです。

    <a href="?no=%d"><img src="data:%s;base64,%s" alt="%s" width="200px"/></a>', $row['no'], image_type_to_mime_type($row['type']), base64_encode($row['thumb_data']), h($row['name'])

    の<a href="?no=%d">ここの部分だと思います!

    キャンセル

  • 2016/01/27 17:38 編集

    PHP のコードの $_GET["id"] に入るようにしたいのであれば、href部分 の Key の指定は "no" ではなく "id" のにする必要がある・・・ということじゃないかな。

    × href="?no=%d"
    ○ href="?id=%d"

    補足事項:
    > header('Content-Type: text/html; charset=UTF-8');
    この一文をすべての処理の最初に設定しているので、どうあってもブラウザはサーバーからの返却値を ”text/html" と解釈してしまいます。
    HTMLを返却する場合のみ、上記ヘッダをセットするようにして見てください。

    キャンセル

  • 2016/01/27 17:45

    × href="?no=%d"
    ○ href="?id=%d"
    この方法で出来ました!
    本当にありがとうございます!

    キャンセル

0

aタグはリンクタグなので、その先に原寸表示用のページを作る必要があるのではないかと思います。
row["no"]は数字のようなので、おそらくidか何かだと思いますが、当然番号にリンクしても何も起こりません。
photo.phpか何かを作り、そちらにGETでidを飛ばして、受け取ったIDからバイナリデータを取得、表示という作業が必要なように思います。

表示のさせ方については以下が使えそうかな?と思います。
画像をデータベースに保存、ブラウザで表示する

単純にリンクだけで見れるようにしたいのであれば、DBでなくどこかに直接元画像を保存し、そのパスをDBに格納してaタグの飛び先にしてあげれば大丈夫です。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • ただいまの回答率 89.20%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる
  • トップ
  • PHPに関する質問
  • 【php+mysql】画像をアップロードしてデータベースにサムネイル画像と共に保存して、それを表示したい