勉強したことのメモ

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

  関連記事

JavaScriptにて電子書籍や漫画ビューア用のライブラリ「ToraViewer」の利用方法
JavaScriptにて電子書籍や漫画ビューア用のライブラリ「ToraViewer」の利用方法

電子書籍や漫画ビューア用を設置したい。条件としてはレスポンシブ対応していること。 ...

PHPでファイル書き込み時に「failed to open stream: HTTP~~」エラー
PHPでファイル書き込み時に「failed to open stream: HTTP~~」エラー

PHPでファイルを書き込む際に「failed to open stream: H ...

Lightboxの最新版ライブラリ「Lightbox3」の利用方法サンプル
Lightboxの最新版ライブラリ「Lightbox3」の利用方法サンプル

画像拡大(モーダル表示)系のライブラリはLightbox2を使用していたが、最新 ...

lazyload.js等のライブラリを使わずHTMLのみで画像の遅延読み込みを行う方法
lazyload.js等のライブラリを使わずHTMLのみで画像の遅延読み込みを行う方法

画像を遅延読み込みさせるとなるとだいぶ前に書いたlazyload.jsを用いる方 ...

PHPで画像を分割し並べ替えて出力したものをJavaScriptで復元する方法
PHPで画像を分割し並べ替えて出力したものをJavaScriptで復元する方法

ある電子書籍サイトをブラウザの開発者ツールで見てみたところ、PHPでページ画像を ...