首页 > 解决方案 > 将文件上传限制为一个文件 - PHP

问题描述

我有一个文件输入元素,用于将个人资料图片上传到用户个人资料页面。默认情况下,浏览器只允许此元素上传一个文件,除非您添加该multiple属性。

我想在 PHP 中设置一个备份,以防万一有人决定在 HTML 中添加“多个”属性。

我认为$_POST将超全局分配给一个变量并使用 if 语句说明该值是否大于 1 会阻止这种情况,但事实并非如此?

解决这个问题的最佳方法是什么?我尝试了各种方法,例如count()数组方法,但似乎无法找到解决看似非常简单的问题的方法?

if(isset($_POST['submit-profile-image'])) {

    $profileImage = $_POST['submit-profile-image'];

    if (isset($profileImage)) {
        if ($profileImage > 1) {
            $error[] = "You cannot upload more than one profile image";
        }
    }
    // ALL OTHER CODE
}

我也尝试过使用$_FILES超全局并计算$_FILES['profile-image']. 这遇到了一个不同的问题,它阻止了多个文件上传但也阻止了单个文件上传(我不明白为什么)?

if(isset($_FILES['profile-image'])){
    if(count($_FILES['profile-image']) > 1){
        $error[] = "You cannot upload more than one profile image";
    }
}

标签: phpfilefile-uploadlimit

解决方案


您无法阻止用户发送多个文件。你所能做的就是防御这种可能性,优雅地失败。

假设您的 HTML 包含此内容<form>

<form method='post' enctype="multipart/form_data">
  <input type='file' name='uploadFile'>
  <input type='submit' name='submit'>
</form>

当用户选择一个文件并单击submit时,浏览器将文件打包并发送,PHP 将文件解包到服务器磁盘,然后将文件详细信息呈现给$_FILES['uploadFile']数组中的程序。

如果我们假设用户编辑您的 HTML 并添加,multiple那么浏览器将打包文件并发送它们。PHP 将解压第一个文件并$_FILES['uploadFile']像以前一样添加其详细信息。然后它将解压缩第二个文件并将其详细信息放入$_FILES['uploadFile'],覆盖第一个文件。您的程序只看到一个文件,对任何其他文件一无所知,然后继续执行。

要获取两个文件,您的用户必须更改file输入的名称以使用数组语法,因此假设他将行更改为

  <input type='file' name='uploadFile[]' multiple>

现在 PHP 将文件详细信息解压缩到一组数组中。它不是$_FILES['uploadFile']['name']包含一个文件名的字符串,而是一个字符串数组。

您的代码(期望字符串)很可能会阻塞数组并以某种意想不到的方式失败。您可以检查这种情况

if (is_array($_FILES['uploadFile']['name'])) {throw new Exception("Too many files");}

所以,我们的用户,决定将这个额外的文件强加给你,现在<input>在表单中添加了第二个:

<form method='post' enctype="multipart/form_data">
  <input type='file' name='uploadFile'>
  <input type='file' name='uploadFile'>
  <input type='submit' name='submit'>
</form>

第二个文件覆盖第一个文件,因为它具有相同的名称。你的程序并不聪明,只使用一个文件。所以用户在第二个更改名称input

<form method='post' enctype="multipart/form_data">
  <input type='file' name='uploadFile'>
  <input type='file' name='uploadFileB'>
  <input type='submit' name='submit'>
</form>

您可以通过查看来检查这一点count($_FILES),但您的程序并没有在寻找第二个输入,所以它无论如何都会忽略它并继续处理第一个文件。如果用户还更改了第一个名称,您的程序将看不到任何文件,并且如果他颠倒名称,您的程序将只看到第二个文件而忽略第一个文件。

或者,在 PHP.INI 中设置 PHP 配置值:

max_file_uploads = 1;

如果这样做,PHP 将忽略第二个和后续文件。您的代码仍需处理命名问题。设置它ini_set()似乎没有任何效果。


推荐阅读