【问题标题】:PHP how to display folder and its content while also being able to download the contentPHP如何显示文件夹及其内容,同时还能够下载内容
【发布时间】:2022-01-03 16:44:24
【问题描述】:

所以我正在尝试创建一个文件服务器,

基本上它应该工作的方式是你有很多包含文件的文件夹,当你点击一个文件时,你会下载它,如果它是一个文件夹,你可以打开它并查看其中的内容。

我的问题是如何创建这样的系统?我一直在尝试使用 FilesystemIterator 但我不知道如何继续。

这是我正在使用的 PHP 代码,该代码设置在 div 元素内

 <?php 
        $filesInFolder = array();
        $directory = "src";
        $iterator = new FilesystemIterator($directory);

        foreach($iterator as $entry){
            $filesInFolder[] = $entry->getFilename();
        }

        foreach($filesInFolder as $file){
            echo "<a href='/$file'> $file </a>";
        }
  ?>

这是我的文件结构 file structure

我知道可以创建这个,我只是不知道如何创建它。

【问题讨论】:

    标签: php file browser iterator filesystems


    【解决方案1】:

    我对你的代码做了一些重构:

    $filesInFolder = array();
    $baseDir       = "/var/www/html/test";
    $currentDir    = !empty($_GET['dir']) ? $_GET['dir'] : $baseDir;
    $currentDir    = rtrim($currentDir, '/');
    
    if (isset($_GET['download'])) {
        //you could provide another logic to present requested file
        readfile($_GET['download']);
        exit;
    }
    
    $iterator = new FilesystemIterator($currentDir);
    echo "<h3>" . $iterator->getPath() . "</h3>";
    
    foreach ($iterator as $entry) {
        $name = $entry->getBasename();
    
        if (is_dir($currentDir . '/' . $name)) {
            echo "D: <a href='?dir=" . $currentDir . "/" . $name . "'>" . $name . "</a><br />";
        } elseif (is_file($currentDir . '/' . $name)) {
            echo "F: <a href='?download=" . $currentDir . '/' . $name . "' download='" . $name . "'> " . $name . " </a><br />";
        }
    }
    

    您必须非常小心,因为攻击者可以轻松地将查询更改为 ?dir=../../ 并访问您的文件系统。 所以你必须自己防止这种情况发生。

    编辑:它不能 100% 工作,但我正在努力尽快提供正确的答案

    Edit2:代码重构为工作

    【讨论】:

      【解决方案2】:

      这就是你的做法。 首先你像这样创建一个 FileReader.php 文件(我还添加了图标和文件大小,你需要创建所有图标所在的图标文件夹)

      <?php
      /**
       * File reader, reads directory and outputs it in an array
       */
      class FileReader {
      
          public function __construct(
              public string $root
          ) {}
          
          /**
           * @param string $path 
           */
          public function removeRootFromPath( $path) {
              $path = preg_replace('/' . preg_quote($this->root, '/') . '/', '', $path);
              $path = $this->cleanPath($path);
              return DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR);
          }
      
          /**
           * @param string $path
           */
          public function addRootToPath( $path) {
              $path = $this->removeRootFromPath($path);
              $path = ltrim($path, DIRECTORY_SEPARATOR);
              $root = rtrim($this->root, DIRECTORY_SEPARATOR);
              return $root . DIRECTORY_SEPARATOR . $path;
          }
      
          /**
           * @param string $dir Directory to load
           */
          public function cleanPath( $dir) {
              $sep = preg_quote(DIRECTORY_SEPARATOR, '/');
              return preg_replace('/\.\.' . $sep . '|\.' . $sep . '/', '', $dir);
          }
      
          /**
           * @param string $dir Directory to load
           * @return FilesystemIterator|null
           */
          public function readDirectory( $dir) {
              $dir = $this->addRootToPath($dir);
      
              try {
                  return new FilesystemIterator($dir, FilesystemIterator::SKIP_DOTS);
              } catch (UnexpectedValueException $exception) {
                  return null;
              }
          }
      
          /** 
          * @param string $size File size in bytes
          * @param int $precision File size conversion precision
          * @return string round($size, $precision).$units[$i] 
          */
      
          public function humanFilesize($size, $precision = 1) {
              $units = array(' B',' kB',' MB',' GB',' TB',' PB',' EB',' ZB',' YB');
              $step = 1024;
              $i = 0;
              while (($size / $step) > 0.9) {
                  $size = $size / $step;
                  $i++;
              }
              return round($size, $precision).$units[$i];
          }
      
          /** 
          * @param string $file File to load
          * @return string $type <- File type
          * @return string $image <- File image
          */
          public function returnFileExtensionAndImage($file) {
      
              $val = strtolower($file);
              switch($val) {
              case "avi":
                  $type = "Video file";
                  $image = "avi.png";
                  break;
              case "bat":
                  $type = "Batch file";
                  $image = "bat.png";
                  break;
              case "css":
                  $type = "Cascading Style Sheet";
                  $image = "txt.png";
                  break;
              case "exe":
                  $type = "Executable file";
                  $image = "exe.png";
                  break;
              case "fla":
                  $type = "Flash file";
                  $image = "fla.png";
                  break;
              case "gif":
                  $type = "GIF Image";
                  $image = "gif.png";
                  break;
              case "html":
                  $type = "HTML file";
                  $image = "html.png";
                  break;
              case "htm":
                  $type = "HTM file";
                  $image = "html.png";
                  break;
              case "jpg":
                  $type = "JPEG Image";
                  $image = "jpg.png";
                  break;
              case "mp3":
                  $type = "Music File";
                  $image = "mp3.png";
                  break;
              case "msg":
                  $type = "Email message";
                  $image = "msg.png";
                  break;
              case "pdf":
                  $type = "PDF file";
                  $image = "pdf.png";
                  break;
              case "psd":
                  $type = "Photoshop file";
                  $image = "psd.png";
                  break;
              case "php":
                  $type = "PHP file";
                  $image = "php.png";
                  break;
              case "ppt":
                  $type = "PowerPoint presentation";
                  $image = "ppt.png";
                  break;
              case "pptx":
                  $type = "PowerPoint presentation";
                  $image = "ppt.png";
                  break;
              case "swf":
                  $type = "SWF Flash file";
                  $image = "swf.png";
                  break;
              case "txt":
                  $type = "Text file";
                  $image = "txt.png";
                  break;
              case "csv":
                  $type = "CSV file";
                  $image = "txt.png";
                  break;
      
              case "wma":
                  $type = "Windows Media Audio";
                  $image = "wma.png";
                  break;
              case "xls":
                  $type = "Excel file";
                  $image = "xls.jpg";
                  break;
              case "xlsx":
                  $type = "Excel file";
                  $image = "xls.jpg";
                  break;
              case "zip":
                  $type = "Zip file";
                  $image = "zip.png";
                  break;
              case "7zip":
                  $type = "Zip file";
                  $image = "zip.png";
                  break;
              case "zip":
                  $type = "Zip file";
                  $image = "zip.png";
              case "7z":
                  $type = "7Zip file";
                  $image = "rar.png";
                  break;
              case "doc":
                  $type = "Word document";
                  $image = "doc.png";
                  break;
              case "docx":
                  $type = "Word document";
                  $image = "doc.png";
                  break;
              case "docs":
                  $type = "Word document";
                  $image = "doc.png";
              case "rar":
                  $type = "Rar file";
                  $image = "rar.png";
              //--- New Here---//
              default:
                  $type = "Unknown file";
                  $image = "unknown.jpg";
              }
              return $type . "?" . $image;
          }
      }
      ?>
      

      然后您创建 FileTable.php,其中将显示您的所有文件和文件夹,您将能够访问它们并下载选定的文件(仅文件而不是文件夹)+(我添加了简单过滤)

          <?php 
      $cleanPath = $target;
      
      /**
       * CURRENT DIRECTORY LOCATION DISPLAY FIX
       */
      switch (strlen($cleanPath)) {
          case 1:
              $cleanPath[0] = " ";
              break;
      
          case 2:
              if($cleanPath[0] == "\\" && $cleanPath[1] == "/"){
                  $cleanPath[0] = " ";
                  $cleanPath[1] = " ";
                  $cleanPath[2] = " ";
                  break;
              }else {
                  $cleanPath[0] = " ";
                  break;
              }
          default:
              $cleanPath[0] = " ";
              break;
      }
      
      /**
       * HERE WRITE ALL FILES YOU WANT FileReader TO IGNORE
       * - WRITE file + its extension
       * - FOR DIRECTORY WRITE THE NAME OF THE DIRECTORY TO IGNORE
       */
      $filesToIgnore = [
          'index.php',
          'index.css',
          'index.html',
          'Restricted',
          'PUT YOUR FILES HERE.txt'
      ];
      ?>
      
      <?php if(strlen($target) != 0): ?>
          <p class="CurrentFolderLocation"><?= $cleanPath; ?></p>
      <?php else: ?>
          <p class="CurrentFolderLocation"></p>
      <?php endif ?>
      
      <table class="FileTable">
          <div class="InputArea">
              <input type="text" id="filterInput" onkeyup="filterTable()" placeholder="Name of the file to search for...">
          </div>
          <thead class="TableHead">
              <tr>
                  <th>
                      <a class="ReturnImg"  href="?path=<?= urlencode($reader->removeRootFromPath(dirname($target))); ?>">
                          <img src= "../Components/icons/levelup.png" alt="level up"/>
                      </a> 
                  </th>
                  <th>File name</th>
                  <th>File size</th>
                  <th>File type</th>
                  <th>Last file modification date</th>
              </tr>
              
          </thead>
          <tbody id="tableBody" class="TableBody">            
              <?php if ($results = $reader->readDirectory($target)): ?>
                  <?php foreach($results as $result): ?>
                      <?php
                          $currentFileToCheck = explode("\\",$result);
                          $currentFileToCheck = $currentFileToCheck[array_key_last($currentFileToCheck)];
                      ?>
                      <?php if(!in_array($currentFileToCheck,$filesToIgnore)): ?>
                          <tr>
                              <?php
      
                              // Make the full path user friendly by removing the root directory.
                              $user_friendly = $reader->removeRootFromPath($result->getFileInfo());
      
                              //File information
                              $fileName = pathinfo($result,PATHINFO_BASENAME);
                              $fileInfo = explode("?",($reader->returnFileExtensionAndImage(pathinfo($result,PATHINFO_EXTENSION))),2);
                              $fileExtension = $fileInfo[0];
                              $fileIcon = $iconsPath . $fileInfo[1];
                              $fileDateModified = explode(" ",date("F d.Y - H:i:s",filemtime($result)),4);
                              $fileDateModified = implode(" ",$fileDateModified);
      
                              $type = $result->getType();
                                  if($type !== 'dir'){
                                      $fileSize = $reader->humanFilesize(filesize($result));
                                  }
                              ?>
          
                              <?php if($type === 'dir'): ?>
                                  <td><img class="FileImage" src="../Components/icons/folder.jpg"></td>
                                  <td>
                                      <a href="?path=<?= urlencode($user_friendly); ?>"><?= $fileName; ?></a>
                                  </td>
                                  <td></td>
                                  <td></td>
                                  <td></td>
                              <?php else: ?>  
                                  <td><img class="FileImage" src=<?= $fileIcon; ?> alt="Ikonka souboru"></td>
      
                                  <?php if(pathinfo($result,PATHINFO_EXTENSION) == "pdf"): ?>
                                      <td><a target="_blank" href="./<?= $user_friendly; ?>"><?= $fileName; ?></a></td>
                                  <?php else: ?>
                                      <td><a download href="./<?= $directoryToScan . "/" . $user_friendly; ?>"><?= $fileName; ?></a></td>
                                  <?php endif ?>
      
                                  <td><?= $fileSize; ?></td>
                                  <td><?= $fileExtension; ?></td>
                                  <td><?= $fileDateModified; ?></td>
      
                              <?php endif ?>
                          </tr>
                      <?php endif ?>
                  <?php endforeach ?>
              <?php else: ?>
                  <tr>
                      <td></td>
                      <td>Directory/File doesn't exist</td>
                      <td></td>
                      <td></td>
                      <td></td>
                  </tr>
              <?php endif ?>
          </tbody>
      </table>
      
      <script>
          function filterTable() {
          // Declare variables
          let input = document.getElementById("filterInput"),
              filter = input.value.toUpperCase(),
              table = document.getElementById("tableBody"),
              tr = table.getElementsByTagName("tr"),
              td, 
              i, 
              txtValue;
      
      
          // Loop through all table rows, and hide those who don't match the search query
          for (i = 0; i < tr.length; i++) {
              td = tr[i].getElementsByTagName("td")[1];
                  if (td) {
                      txtValue = td.textContent || td.innerText;
                      if (txtValue.toUpperCase().indexOf(filter) > -1) {
                          tr[i].style.display = "";
                      } else {
                          tr[i].style.display = "none";
                      }
                  }
              }
          }
      </script>
      

      最后您将创建 index.php 并将其连接在一起

          <?php
      
      $path = $_SERVER['DOCUMENT_ROOT']; // Get Root path of your file system
      
      $componentPath = $path . "/Components/";
      $componentFileReader = $componentPath . "FileReader.php";
      $componentFileTable = $componentPath . "FileTable.php";
      
      $iconsPath = "/Components/icons/";
      $cssStyle = "./Components/index.css";
      
      include($componentFileReader);
      $directoryToScan = 'src'; // Relative to current file. Change to your path!
      $reader = new FileReader(__DIR__ . DIRECTORY_SEPARATOR . $directoryToScan);
      $target = $reader->removeRootFromPath(!empty($_GET['path']) ? $_GET['path'] : '/');
      
      ?>
      
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          
          <link rel="stylesheet" href=<?=$cssStyle; ?>> 
          <title>File browser</title>
          
      </head>
      <body>
      
          <main class="PageBody flex-column">
              <?php include($componentFileTable) ?>
          </main>
      
      </body>
      </html>
      

      如果您需要它 -> CODE HERE 如果您使用 Apache,只需下载并将其放入您的 htdocs 文件夹中

      【讨论】:

        猜你喜欢
        • 2014-04-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-11
        • 2016-03-17
        • 2012-09-19
        • 1970-01-01
        • 1970-01-01
        • 2010-12-21
        相关资源
        最近更新 更多