勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

formのinput="file"でディレクトリを選択させ、ディレクトリ内のファイルを全てアップロードする方法

  PHP HTML

フォームで複数のファイルをアップロードしたい場合、input="file"を複数設置するもしくはファイルをzip圧縮してもらってzipファイル形式でアップロードする方法を取っていた。調べたところinput="file"でディレクトリを選択させる方法が見つかった。以下に実装方法をメモ。

 

リファレンス

PHP側

https://www.php.net/manual/ja/features.file-upload.multiple.php

HTML側

https://developer.mozilla.org/ja/docs/Web/API/HTMLInputElement/webkitdirectory

input="file"にwebkitdirectoryプロパティを追加することでディレクトリが選択できるようになるみたい。

 

ソースコード

フォーム側(index.php)

<html lang="ja">
<head>
    <meta charset="utf-8">
</head>
<body>
    <form action="upload.php" method="post" enctype="multipart/form-data">
        <input type="file" name="file[]" id="file" webkitdirectory>
        <input type="submit" name="submit" value="送信">
        <div id="hidden"></div>
    </form>
</body>
</html>

webkitdirectoryプロパティを付与するのとnameはfile[]と配列型にすること。

アップロード側(upload.php)

<?php
require_once 'class.upload.php';

$lang = 'ja_JP';

$file_ary = array();
$file_count = count($_FILES['file']['name']);
$file_keys = array_keys($_FILES['file']);

for( $i = 0; $i < $file_count; $i++ ){
    foreach( $file_keys as $key ) {
        $file_ary[$i][$key] = $_FILES['file'][$key][$i];
    }
}

$count = 0;
foreach( $file_ary as $file ){

    $count++;
    $handle = new \Verot\Upload\Upload($file, $lang);

    if( $handle->uploaded ){

        //ファイル名の変更
        $handle->file_new_name_body = date('YmdHis_' . $count);

        //同一ファイル名の場合は上書き
        $handle->file_overwrite = true;

        //アップロードするディレクトリ指定
        $handle->process('./file/');
        if( $handle->processed ){
            //成功処理
            echo 'success';

        }else{
            //エラー処理
            echo $handle->error;
        }

    }else{
        //エラー処理
        echo $handle->error;
    }

}

解説

複数ファイルを送信した際にPHP側では以下の形で受け取ることになる。

array(1) {
  ["file"]=>
  array(5) {
    ["name"]=>
    array(2) {
      [0]=>
      string(8) "test.txt"
      [1]=>
      string(9) "test2.txt"
    }
    ["type"]=>
    array(2) {
      [0]=>
      string(10) "text/plain"
      [1]=>
      string(10) "text/plain"
    }
    ["tmp_name"]=>
    array(2) {
      [0]=>
      string(14) "/tmp/phpCeNojc"
      [1]=>
      string(14) "/tmp/phpqrHtpX"
    }
    ["error"]=>
    array(2) {
      [0]=>
      int(0)
      [1]=>
      int(0)
    }
    ["size"]=>
    array(2) {
      [0]=>
      int(4)
      [1]=>
      int(5)
    }
  }
}

このような形だと処理しづらいので以下部分で整形している。

$file_ary = array();
$file_count = count($_FILES['file']['name']);
$file_keys = array_keys($_FILES['file']);

for( $i = 0; $i < $file_count; $i++ ){
    foreach( $file_keys as $key ) {
        $file_ary[$i][$key] = $_FILES['file'][$key][$i];
    }
}

整形後は以下のような見慣れた形になる。

array(2) {
  [0]=>
  array(5) {
    ["name"]=>
    string(8) "test.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(14) "/tmp/phpqoEkKv"
    ["error"]=>
    int(0)
    ["size"]=>
    int(4)
  }
  [1]=>
  array(5) {
    ["name"]=>
    string(9) "test2.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(14) "/tmp/phpfelQzi"
    ["error"]=>
    int(0)
    ["size"]=>
    int(5)
  }
}

 

所感

今回はディレクトリ内のファイルを全部アップロードするという形だったが、ディレクトリ構造丸ごとアップロードもできるらしい。こちらも後日試してみたいところ。

 - PHP HTML

  関連記事

「slick」でブラウザ幅がPCの場合はスライダーを表示し、スマホ幅の場合はスライダー無しにする方法
「slick」でブラウザ幅がPCの場合はスライダーを表示し、スマホ幅の場合はスライダー無しにする方法

slickプラグインで画像スライダーを設置しているページがあり、PCのブラウザ幅 ...

PHPで画像のフォーマット(拡張子)の変換
PHPで画像のフォーマット(拡張子)の変換

画像のアップロードでjpg/png/gif形式を受け付けつつ、 最終的にjpgで ...

PHPでダミー画像(プレースホルダー画像)を表示する「PHP-Dummy-Image-Generator」の利用方法
PHPでダミー画像(プレースホルダー画像)を表示する「PHP-Dummy-Image-Generator」の利用方法

先日JavaScriptでダミー画像(プレースホルダー画像)を表示する「Hold ...

サムネイルをクリックすると拡大画像を表示できる「Lightbox」の利用方法
サムネイルをクリックすると拡大画像を表示できる「Lightbox」の利用方法

画像をサムネイル表示してクリックしたら大きく表示する というのがLightbox ...

summernoteで画像選択時にサーバにファイルをアップロードする方法
summernoteで画像選択時にサーバにファイルをアップロードする方法

summernoteで画像を選択した際、ファイルはアップロードされずBase64 ...