限制用户php上的文件上传

时间:2017-05-14 23:06:29

标签: php

我是新来的php请帮助我,我有一个网站,人们可以上传pdf,doc,xls等文件,我想限制文件上传的数量。登录后的用户可以看到上传页面并上传他的文件,但我希望用户每天只能上传文件3次,如果他一天提交3次,那么它不应该允许用户上传更多的文件消息,你不能每天发布3个以上的项目。

My files are: form.php and Uploadfile.php


<?php 
use foundationphp\UploadFile;

session_start();
require_once 'src/foundationphp/UploadFile.php';
if (!isset($_SESSION['maxfiles'])) {
    $_SESSION['maxfiles'] = ini_get('max_file_uploads');
    $_SESSION['postmax'] = UploadFile::convertToBytes(ini_get('post_max_size'));
    $_SESSION['displaymax'] = UploadFile::convertFromBytes($_SESSION['postmax']);
}
$max = 2000000;
$result = array();
if (isset($_POST['upload'])) {

    $destination = __DIR__ . '/uploaded/';
    try {
        $upload = new UploadFile($destination);
        $upload->setMaxSize($max);
        // $upload->allowAllTypes();
        $upload->upload();
        $result = $upload->getMessages();
    } catch (Exception $e) {
        $result[] = $e->getMessage();
    }
}
$error = error_get_last();
?>
<!DOCTYPE HTML>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>File Uploads</title>
    <link href="styles/form.css" rel="stylesheet" type="text/css">
</head>
<body>
    <h1>Uploading Files</h1>
    <?php if ($result || $error) { ?>
    <ul class="result">
        <?php 
        if ($error) {
            echo "<li>{$error['message']}</li>";
        }
        if ($result) {
           foreach ($result as $message) {
               echo "<li>$message</li>";
           }
       }?>
   </ul>
   <?php } ?>
   <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post" enctype="multipart/form-data">
    <p>
        <input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $max;?>">
        <label for="filename">Select File:</label>
        <input type="file" name="filename[]" id="filename" multiple
        data-maxfiles="<?php echo $_SESSION['maxfiles'];?>"
        data-postmax="<?php echo $_SESSION['postmax'];?>"
        data-displaymax="<?php echo $_SESSION['displaymax'];?>">
    </p>
    <ul>
        <li>Up to <?php echo $_SESSION['maxfiles'];?> files can be uploaded simultaneously.</li>
        <li>Each file should be no more than <?php echo UploadFile::convertFromBytes($max);?>.</li>
        <li>Combined total should not exceed <?php echo $_SESSION ['displaymax'];?>.</li>
    </ul>
    <p>
        <input type="submit" name="upload" value="Upload File">
    </p>
</form>
<script src="js/checkmultiple.js"></script>
</body>
</html>


And uploadfile.php

<?php
namespace foundationphp;

class UploadFile
{
    protected $destination;
    protected $messages = array();
    protected $maxSize = 2102400;//51200; //50 KB
    protected $permittedTypes = array(
            'image/jpeg',
            'image/pjpeg',
            'image/gif',
            'image/png',
            'image/webp',
            'application/pdf',
            'application/rar',
            'application/zip',
            'application/x-zip',
            'application/x-zip-compressed',
            'application/vnd.ms-excel',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/vnd.ms-powerpoint',
            'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'application/vnd.oasis.opendocument.spreadsheet',
            'application/vnd.oasis.opendocument.presentation',
            'application/vnd.oasis.opendocument.text'   


    );
    protected $newName;
    protected $typeCheckingOn = true;
    protected $notTrusted = array('bin', 'cgi', 'exe', 'dmg', 'js', 'pl', 'php', 'py', 'sh');
    protected $suffix = '.upload';
    protected $renameDuplicates;

    public function __construct($uploadFolder)
    {
        if (!is_dir($uploadFolder) || !is_writable($uploadFolder)) {
            throw new \Exception("$uploadFolder must be a valid, writable folder.");
        }
        if ($uploadFolder[strlen($uploadFolder)-1] != '/') {
            $uploadFolder .= '/';
        }
        $this->destination = $uploadFolder;
    }

    public function setMaxSize($bytes)
    {
        $serverMax = self::convertToBytes(ini_get('upload_max_filesize'));
        if ($bytes > $serverMax) {
            throw new \Exception('Maximum size cannot exceed server limit for individual files: ' . self::convertFromBytes($serverMax));
        }
        if (is_numeric($bytes) && $bytes > 0) {
            $this->maxSize = $bytes;
        }
    }

    public static function convertToBytes($val)
    {
        $val = trim($val);
        $last = strtolower($val[strlen($val)-1]);
        if (in_array($last, array('g', 'm', 'k'))){
            switch ($last) {
                case 'g':
                    $val *= 1024;
                case 'm':
                    $val *= 1024;
                case 'k':
                    $val *= 1024;
            }
        }
        return $val;
    }

    public static function convertFromBytes($bytes)
    {
        $bytes /= 1024;
        if ($bytes > 1024) {
            return number_format($bytes/1024, 1) . ' MB';
        } else {
            return number_format($bytes, 1) . ' KB';
        }
    }

    public function allowAllTypes($suffix = null)
    {
        $this->typeCheckingOn = false;
        if (!is_null($suffix)) {
            if (strpos($suffix, '.') === 0 || $suffix == '') {
                $this->suffix = $suffix;
            } else {
                $this->suffix = ".$suffix";
            }
        }
    }

    public function upload($renameDuplicates = true)
    {
        $this->renameDuplicates = $renameDuplicates;
        $uploaded = current($_FILES);
        if (is_array($uploaded['name'])) {
            foreach ($uploaded['name'] as $key => $value) {
                $currentFile['name'] = $uploaded['name'][$key];
                $currentFile['type'] = $uploaded['type'][$key];
                $currentFile['tmp_name'] = $uploaded['tmp_name'][$key];
                $currentFile['error'] = $uploaded['error'][$key];
                $currentFile['size'] = $uploaded['size'][$key];
                if ($this->checkFile($currentFile)) {
                    $this->moveFile($currentFile);
                }
            }
        } else {
            if ($this->checkFile($uploaded)) {
                $this->moveFile($uploaded);
            }
        }
    }

    public function getMessages()
    {
        return $this->messages;
    }

    protected function checkFile($file)
    {
        if ($file['error'] != 0) {
            $this->getErrorMessage($file);
            return false;
        }
        if (!$this->checkSize($file)) {
            return false;
        }
        if ($this->typeCheckingOn) {
            if (!$this->checkType($file)) {
                return false;
            }
        }
        $this->checkName($file);
        return true;
    }

    protected function getErrorMessage($file)
    {
        switch($file['error']) {
            case 1:
            case 2:
                $this->messages[] = $file['name'] . ' is too big: (max: ' . 
                self::convertFromBytes($this->maxSize) . ').';
                break;
            case 3:
                $this->messages[] = $file['name'] . ' was only partially uploaded.';
                break;
            case 4:
                $this->messages[] = 'No file submitted.';
                break;
            default:
                $this->messages[] = 'Sorry, there was a problem uploading ' . $file['name'];
                break;
        }
    }

    protected function checkSize($file)
    {
        if ($file['size'] == 0) {
            $this->messages[] = $file['name'] . ' is empty.';
            return false;
        } elseif ($file['size'] > $this->maxSize) {
            $this->messages[] = $file['name'] . ' exceeds the maximum size for a file ('
                    . self::convertFromBytes($this->maxSize) . ').';
            return false;
        } else {
            return true;
        }
    }

    protected function checkType($file) 
    {
        if (in_array($file['type'], $this->permittedTypes)) {
            return true;
        } else {
            $this->messages[] = $file['name'] . ' is not permitted type of file.';
            return false;
        }
    }

    protected function checkName($file)
    {
        $this->newName = null;
        $nospaces = str_replace(' ', '_', $file['name']);
        if ($nospaces != $file['name']) {
            $this->newName = $nospaces;
        }
        $nameparts = pathinfo($nospaces);
        $extension = isset($nameparts['extension']) ? $nameparts['extension'] : '';
        if (!$this->typeCheckingOn && !empty($this->suffix)) {
            if (in_array($extension, $this->notTrusted) || empty($extension)) {
                $this->newName = $nospaces . $this->suffix;
            }
        }
        if ($this->renameDuplicates) {
            $name = isset($this->newName) ? $this->newName : $file['name'];
            $existing = scandir($this->destination);
            if (in_array($name, $existing)) {
                $i = 1;
                do {
                    $this->newName = $nameparts['filename'] . '_' . $i++;
                    if (!empty($extension)) {
                        $this->newName .= ".$extension";
                    }
                    if (in_array($extension, $this->notTrusted)) {
                        $this->newName .= $this->suffix;
                    }
                } while (in_array($this->newName, $existing));
            }
        }
    }

    protected function moveFile($file)
    {
        $filename = isset($this->newName) ? $this->newName : $file['name'];
        $success = move_uploaded_file($file['tmp_name'], $this->destination . $filename);
        if ($success) {
            $result = $file['name'] . ' was uploaded successfully';
            if (!is_null($this->newName)) {
                $result .= ', and was renamed ' . $this->newName;
            }
            $result .= '.';
            $this->messages[] = $result;
        } else {
            $this->messages[] = 'Could not upload ' . $file['name'];
        }
    }
}
Thanks/Regards,

Sam

3 个答案:

答案 0 :(得分:0)

您可以使用SQL来存储每个用户上传的文件数量。然后你可以检查php是否用户可以使用SQL查询上传另一个文件。

<强> 编辑:

让我们详细说明一下。

实现这一目标有两种方法:

a)服务器端。

正如您所说,您有一个登录表单。我想你有一个包含用户名和密码的数据库,对吧?因此,您可以在数据库中添加“上传”表格,其中包含每次上传的时间戳和上传者的用户名。

然后,每次调用PHP类时,您都可以查询数据库,以查看上传者在过去24小时内上传的文件数量。如果数字<3,那么您的PHP类将允许他上传另一个。否则,您的PHP类将回显您想要的消息。

b)客户端。

每次用户上传文件时,有关其上传的信息都会存储在他的localStorage中。因此,将在“上传”按钮点击事件中检查此信息,并允许他上传或不上传。

但是,正如我所说,信息存储在HIS localStorage中,因此,此方法可由用户绕过。我不推荐它。

答案 1 :(得分:0)

改进您的上传功能并在UploadFile类中添加目标,以获得更好的可重用性和安全性:

class UploadFile
{
    protected $destination = __DIR__ . '/uploaded/';
    protected $messages = array();
    protected $maxSize = 2102400;//51200; //50 KB
    protected $permittedTypes = array(
            'image/jpeg',
            'image/pjpeg',
            'image/gif',
            'image/png',
            'image/webp',
            'application/pdf',
            'application/rar',
            'application/zip',
            'application/x-zip',
            'application/x-zip-compressed',
            'application/vnd.ms-excel',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/vnd.ms-powerpoint',
            'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'application/vnd.oasis.opendocument.spreadsheet',
            'application/vnd.oasis.opendocument.presentation',
            'application/vnd.oasis.opendocument.text'   


    );
    protected $newName;
    protected $typeCheckingOn = true;
    protected $notTrusted = array('bin', 'cgi', 'exe', 'dmg', 'js', 'pl', 'php', 'py', 'sh');
    protected $suffix = '.upload';
    protected $renameDuplicates;

    public function __construct($uploadFolder)
    {
        if (!is_dir($uploadFolder) || !is_writable($uploadFolder)) {
            throw new \Exception("$uploadFolder must be a valid, writable folder.");
        }
        if ($uploadFolder[strlen($uploadFolder)-1] != '/') {
            $uploadFolder .= '/';
        }
        $this->destination = $uploadFolder;
    }

    public function setMaxSize($bytes)
    {
        $serverMax = self::convertToBytes(ini_get('upload_max_filesize'));
        if ($bytes > $serverMax) {
            throw new \Exception('Maximum size cannot exceed server limit for individual files: ' . self::convertFromBytes($serverMax));
        }
        if (is_numeric($bytes) && $bytes > 0) {
            $this->maxSize = $bytes;
        }
    }

    public static function convertToBytes($val)
    {
        $val = trim($val);
        $last = strtolower($val[strlen($val)-1]);
        if (in_array($last, array('g', 'm', 'k'))){
            switch ($last) {
                case 'g':
                    $val *= 1024;
                case 'm':
                    $val *= 1024;
                case 'k':
                    $val *= 1024;
            }
        }
        return $val;
    }

    public static function convertFromBytes($bytes)
    {
        $bytes /= 1024;
        if ($bytes > 1024) {
            return number_format($bytes/1024, 1) . ' MB';
        } else {
            return number_format($bytes, 1) . ' KB';
        }
    }

    public function allowAllTypes($suffix = null)
    {
        $this->typeCheckingOn = false;
        if (!is_null($suffix)) {
            if (strpos($suffix, '.') === 0 || $suffix == '') {
                $this->suffix = $suffix;
            } else {
                $this->suffix = ".$suffix";
            }
        }
    }

    public function upload($renameDuplicates = true)
    {

$fi = new FilesystemIterator($this->destination, FilesystemIterator::SKIP_DOTS);
$totalFiles = iterator_count($fi);
if ($totalFiles <= 3){
        $this->renameDuplicates = $renameDuplicates;
        $uploaded = current($_FILES);
        if (is_array($uploaded['name'])) {
            foreach ($uploaded['name'] as $key => $value) {
                $currentFile['name'] = $uploaded['name'][$key];
                $currentFile['type'] = $uploaded['type'][$key];
                $currentFile['tmp_name'] = $uploaded['tmp_name'][$key];
                $currentFile['error'] = $uploaded['error'][$key];
                $currentFile['size'] = $uploaded['size'][$key];
                if ($this->checkFile($currentFile)) {
                    $this->moveFile($currentFile);
                }
            }
        } else {
            if ($this->checkFile($uploaded)) {
                $this->moveFile($uploaded);
            }
        }
} else {
    die('You can not post more that 3 projects per day!'); //Improve this to a thrown or stuff;
}
    }

    public function getMessages()
    {
        return $this->messages;
    }

    protected function checkFile($file)
    {
        if ($file['error'] != 0) {
            $this->getErrorMessage($file);
            return false;
        }
        if (!$this->checkSize($file)) {
            return false;
        }
        if ($this->typeCheckingOn) {
            if (!$this->checkType($file)) {
                return false;
            }
        }
        $this->checkName($file);
        return true;
    }

    protected function getErrorMessage($file)
    {
        switch($file['error']) {
            case 1:
            case 2:
                $this->messages[] = $file['name'] . ' is too big: (max: ' . 
                self::convertFromBytes($this->maxSize) . ').';
                break;
            case 3:
                $this->messages[] = $file['name'] . ' was only partially uploaded.';
                break;
            case 4:
                $this->messages[] = 'No file submitted.';
                break;
            default:
                $this->messages[] = 'Sorry, there was a problem uploading ' . $file['name'];
                break;
        }
    }

    protected function checkSize($file)
    {
        if ($file['size'] == 0) {
            $this->messages[] = $file['name'] . ' is empty.';
            return false;
        } elseif ($file['size'] > $this->maxSize) {
            $this->messages[] = $file['name'] . ' exceeds the maximum size for a file ('
                    . self::convertFromBytes($this->maxSize) . ').';
            return false;
        } else {
            return true;
        }
    }

    protected function checkType($file) 
    {
        if (in_array($file['type'], $this->permittedTypes)) {
            return true;
        } else {
            $this->messages[] = $file['name'] . ' is not permitted type of file.';
            return false;
        }
    }

    protected function checkName($file)
    {
        $this->newName = null;
        $nospaces = str_replace(' ', '_', $file['name']);
        if ($nospaces != $file['name']) {
            $this->newName = $nospaces;
        }
        $nameparts = pathinfo($nospaces);
        $extension = isset($nameparts['extension']) ? $nameparts['extension'] : '';
        if (!$this->typeCheckingOn && !empty($this->suffix)) {
            if (in_array($extension, $this->notTrusted) || empty($extension)) {
                $this->newName = $nospaces . $this->suffix;
            }
        }
        if ($this->renameDuplicates) {
            $name = isset($this->newName) ? $this->newName : $file['name'];
            $existing = scandir($this->destination);
            if (in_array($name, $existing)) {
                $i = 1;
                do {
                    $this->newName = $nameparts['filename'] . '_' . $i++;
                    if (!empty($extension)) {
                        $this->newName .= ".$extension";
                    }
                    if (in_array($extension, $this->notTrusted)) {
                        $this->newName .= $this->suffix;
                    }
                } while (in_array($this->newName, $existing));
            }
        }
    }

    protected function moveFile($file)
    {
        $filename = isset($this->newName) ? $this->newName : $file['name'];
        $success = move_uploaded_file($file['tmp_name'], $this->destination . $filename);
        if ($success) {
            $result = $file['name'] . ' was uploaded successfully';
            if (!is_null($this->newName)) {
                $result .= ', and was renamed ' . $this->newName;
            }
            $result .= '.';
            $this->messages[] = $result;
        } else {
            $this->messages[] = 'Could not upload ' . $file['name'];
        }
    }
}

答案 2 :(得分:0)

我认为你的数据库中有一个用户表。只需添加一个新属性upload_day_count ... 在每次上传时,如果没有,则检查数字是否为3,然后您允许上传和icrement此用户的属性值。在00h01min的第+1天,您运行一个cron Job来重置所有用户的所有值。