PHP
MySQL

特定のディレクトリにある画像ファイルをDBに一括アップロードする

やりたいこと

画像データをファイルで管理していたが、ELBの構成の関係でDBに上げる必要が出た為、バイナリデータで一括アップロードをしたい。

実はこれは作ってもらったソースである事は内緒である。

頻繁ではないけど、何かと使うことがある機会があるソースかもしれなくて、役に立てればいいなぁと思ったので公開します。

条件

  • バイナリデータである事
  • IDと紐付いていること

ディレクトリ構造

/public/uploads/facility/以下はIDの中に連番で画像が格納されていた。

/public/uploads/facility/{ID}/jpeg/1.jpg
/public/uploads/facility/{ID}/jpeg/2.jpg

テーブル構造

CREATE TABLE `facility_images` (
  `image_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `facility_id` int(5) unsigned NOT NULL,
  `image` longblob NOT NULL,
  `image_name` varchar(255) NOT NULL DEFAULT '',
  `image_alt` varchar(100) DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`image_id`),
) ENGINE=InnoDB AUTO_INCREMENT=466 DEFAULT CHARSET=utf8;

完成ソース

実際に使用したソースは以下の通り

import-images.php
function filterOutCurrentDirectory($fileNames) {
    return array_filter($fileNames, function ($dirName) {
        return !in_array($dirName, ['.', '..', '.DS_Store'], true);
    });
}


$dirs = scandir('../public/uploads/facility');

$facilityIdList = filterOutCurrentDirectory($dirs);

$imageFileNames = array_map(function ($id) {
    $names = scandir(sprintf('../public/uploads/facility/%d/jpeg', $id));

    $filteredFileNames = filterOutCurrentDirectory($names);

    return [
      'facility_id' => $id,
      'file_names' => $filteredFileNames
    ];
}, $facilityIdList);

$imageFullPathList = array_reduce($imageFileNames, function ($acc, $facility) {
    $facilityId = $facility['facility_id'];

    $pathList = array_map(function ($path) use ($facilityId) {
        return sprintf('../public/uploads/facility/%d/jpeg/%s', $facilityId, $path);
    }, $facility['file_names']);

    return array_merge($acc, $pathList);
}, []);

print_r($imageFullPathList);

foreach ($imageFullPathList as $fullPath) {
    $user = "laravel_kaihuku";
    $pass = "admin";

    $pdo  = new PDO("mysql:host=127.0.0.1;dbname=laravel_kaihuku;charset=utf8", $user, $pass);

    $sql  = "INSERT INTO facility_images( facility_id, image, image_name) VALUES (:facility_id, :image, :image_name);";
    $stmt = $pdo->prepare($sql);
    $stmt->bindValue(":facility_id", explode('/', $fullPath)[4], PDO::PARAM_STR);
    $stmt->bindValue(":image", 'data:image/jpeg;base64,' . base64_encode(file_get_contents($fullPath)), PDO::PARAM_STR);
    //     $stmt->bindValue(":image_name", (new Hashids())->encode(basename($fullPath)), PDO::PARAM_STR);
    $stmt->bindValue(":image_name", basename($fullPath), PDO::PARAM_STR);

    $stmt->execute();
}