[PHP]文件上传示例(PHP → 数据库 → HTML)

将上传的图片注册到数据库并显示的示例。虽然不知道出处,但似乎有一些初学者参考书,许多初学者在将图像数据以二进制方式存储到数据库中后,在显示部分遇到困难,因此我写了一个简单保存图像路径的示例。

然而,我一直在思考为什么要将数据以二进制形式存入数据库,但也可以看出,既涉及文件上传又涉及数据库保存的文章在网络上数量较少,这可能是一个原因。

此外,我很難找到有提到刪除Exif信息的文章。現在的智能手機相機大多預設將位置信息嵌入圖像時關閉,但也有一些情況下可能不知道被打開了。為了預防從發佈的照片中識別出家庭位置等情況,請大家留意。

表格定义

CREATE TABLE `images` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(32) DEFAULT NULL,
  `path` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

文件目录结构

创建一个名为upfiles的目录来保存图像,并按照以下方式进行配置。

ドキュメントルート
┣ upfile/
┣ common.php
┣ image.php
┗ index.php

公共.php

<?php

/**
 * common.php
 */

/**
 * connect_db
 * @return \PDO
 */
function connect_db()
{
    $dsn = 'mysql:host=localhost;dbname=sample;charset=utf8';
    $username = 'root';
    $password = 'password';
    $options = [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
        , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ];
    return new PDO($dsn, $username, $password, $options);
}

/**
 * insert
 * @param string $sql
 * @param array $arr
 * @return int lastInsertId
 */
function insert($sql, $arr = [])
{
    $pdo = connect_db();
    $stmt = $pdo->prepare($sql);
    $stmt->execute($arr);
    return $pdo->lastInsertId();
}

/**
 * select
 * @param string $sql
 * @param array $arr
 * @return array $rows
 */
function select($sql, $arr = [])
{
    $pdo = connect_db();
    $stmt = $pdo->prepare($sql);
    $stmt->execute($arr);
    return $stmt->fetchAll();
}

/**
 * htmlspecialchars
 * @param string $string
 * @return $string
 */
function h($string)
{
    return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
}

index.php -> 网页索引.php

<?php
/**
 * index.php
 */
/**
 * 共通関数読み込み
 */
require 'common.php';

/**
 * file_upload
 */
function file_upload()
{
    // POSTではないとき何もしない
    if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'POST') {
        return;
    }

    // タイトル
    $title = filter_input(INPUT_POST, 'title');
    if ('' === $title) {
        throw new Exception('タイトルは入力必須です。');
    }

    // アップロードファイル
    $upfile = $_FILES['upfile'];

    /**
     * @see http://php.net/manual/ja/features.file-upload.post-method.php
     */
    if ($upfile['error'] > 0) {
        throw new Exception('ファイルアップロードに失敗しました。');
    }

    $tmp_name = $upfile['tmp_name'];

    // ファイルタイプチェック
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mimetype = finfo_file($finfo, $tmp_name);

    // 許可するMIMETYPE
    $allowed_types = [
        'jpg' => 'image/jpeg'
        , 'png' => 'image/png'
        , 'gif' => 'image/gif'
    ];
    if (!in_array($mimetype, $allowed_types)) {
        throw new Exception('許可されていないファイルタイプです。');
    }

    // ファイル名(ハッシュ値でファイル名を決定するため、同一ファイルは同盟で上書きされる)
    $filename = sha1_file($tmp_name);

    // 拡張子
    $ext = array_search($mimetype, $allowed_types);

    // 保存作ファイルパス
    $destination = sprintf('%s/%s.%s'
        , 'upfiles'
        , $filename
        , $ext
    );

    // アップロードディレクトリに移動
    if (!move_uploaded_file($tmp_name, $destination)) {
        throw new Exception('ファイルの保存に失敗しました。');
    }

    // Exif 情報の削除
    $imagick = new Imagick($destination);
    $imagick->stripimage();
    $imagick->writeimage($destination);

    // データベースに登録
    $sql = 'INSERT INTO `images` (`id`, `title`, `path`) VALUES (NULL, :title, :path) ';
    $arr = [];
    $arr[':title'] = $title;
    $arr[':path'] = $destination;
    $lastInsertId = insert($sql, $arr);

    // 成功時にページを移動する
    header(sprintf('Location: image.php?id=%d', $lastInsertId));
}

try {
    // ファイルアップロード
    file_upload();
} catch (Exception $e) {
    $error = $e->getMessage();
}
?>
<!DOCTYPE HTML>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .error {
                color: red;
            }
        </style>
    </head>
    <body>
        <div id="wrap">
            <?php if (isset($error)) : ?>
                <p class="error"><?= h($error); ?></p>
            <?php endif; ?>
            <form action="" method="post" enctype="multipart/form-data">
                <p>
                    <label for="title">タイトル</label>
                    <input type="text" name="title" id="title" />
                </p>
                <p>
                    <label for="upfile">画像ファイル</label>
                    <input type="file" name="upfile" id="upfile" />
                </p>
                <p>
                    <button type="submit">送信</button>
                </p>
            </form>
        </div>
    </body>
</html>

图片.php

<?php
/**
 * image.php
 */
require 'common.php';

try {
    $id = filter_input(INPUT_GET, 'id');

    // データベースからレコードを取得
    $sql = 'SELECT `id`, `title`, `path` FROM `images` WHERE `id` = :id';
    $arr = [];
    $arr[':id'] = $id;
    $rows = select($sql, $arr);
    $row = reset($rows);
} catch (Exception $e) {
    $error = $e->getMessage();
}
?>
<!DOCTYPE HTML>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .error {
                color: red;
            }
        </style>
    </head>
    <body>
        <div id="wrap">
            <?php if (isset($error)) : ?>
                <p class="error"><?= h($error); ?></p>
            <?php endif; ?>

            <p><?= h($row['title']); ?></p>
            <p>
                <img src="<?= h($row['path']); ?>" alt="<?= h($row['title']); ?>" />
            </p>
        </div>
    </body>
</html>
广告
将在 10 秒后关闭
bannerAds