碎碎念

这篇笔记记录使用PHP实现单/多文件上传,涉及文件操作,上传方面的知识哦。

开始

  1. php.ini的配置项

    1. file_uploads = On//文件上传允许的开关
    2. upload_tmp_dir ="c:/wamp64/tmp"//临时上传目录
    3. upload_max_filesize = 2M//最大允许上传大小
    4. post_max_size = 8M//post接受的最大大小
    5. max_file_uploads = 20//最大允许上传数量
  2. 超全局变量$_FILES返回的数组内容(注意临时文件存放的key是tmp_name),其中key指的是input表单的name属性值。

    1. Array
    2. (
    3. [up] => Array
    4. (
    5. [name] => 2020-04-15 下午1.33.43.png
    6. [type] => image/png
    7. [tmp_name] => /Applications/MAMP/tmp/php/php9dYVY9
    8. [error] => 0
    9. [size] => 1350112
    10. )
    11. [up1] => Array
    12. (
    13. [name] => 2020-04-17 下午8.09.34.png
    14. [type] => image/png
    15. [tmp_name] => /Applications/MAMP/tmp/php/phpQ5vWzq
    16. [error] => 0
    17. [size] => 494639
    18. )
    19. )

    error有这么几种取值情况:
    截屏2020-04-19 上午12.37.25.png

  3. 限制上传文件大小:通过HTML标签来限制上传文件的大小,否则如果在后端PHP上判断大小时,文件其实已经在服务器上了。(注意,这个隐藏域必须放在提交文件的上面) ```html

Send this file:

  1. 使用了这个隐藏域之后,可以在用户提交之后,文件上传之前就进行限制判断,超过限制,马上做出$_FILES['error'] = 2的错误。这样就可以避免等一个大文件传上服务器以后才发现超过限制了。这样既浪费了用户的表情,也浪费了我们的带宽。
  2. ```php
  3. <?php
  4. 你上面那个是判断出现错误情况下的,判断有没超过你定义的大小是返回错误为0的情况下进行判断。
  5. if($_FILES['file']['error']>0){
  6. switch($_FILES['file']['error']){
  7. case 1:
  8. echo "上传的文件超过了 php.ini 中7a64e78988e69d8331333337373638 upload_max_filesize 选项限制的值。";
  9. break;
  10. case 2:
  11. echo "上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。";
  12. break;
  13. case 3:
  14. echo "文件只有部分被上传。";
  15. break;
  16. case 4:
  17. echo "没有文件被上传。";
  18. break;
  19. default:
  20. echo "未知错误!";
  21. }
  22. exit;
  23. }
  24. else
  25. {
  26. if($_FILES['file']['size'] > 1000000)
  27. {
  28. echo "上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。";
  29. exit;
  30. }
  31. }
  32. echo "上传成功";
  1. 移动临时文件的安全检测,PHP为此提供了两个函数
    1. is_uploaded_file($临时文件地址);
    2. move_uploaded_file($要移动的文件, 新地址);
  2. 多文件上传的优化:前端表单name字段,如果是多表单上传每次都必须制定不同的name?!此时可以把name指定为imgae[],返回的将是一个image多维数组,返回了多表单的数据。

    最终代码

    PHP实现单/多文件上传

    1. <?php
    2. class FileUploadHandler
    3. {
    4. protected $uploadDir;
    5. public function make(): array
    6. {
    7. $this->makeDir();
    8. $uploadedFiles = [];
    9. $formatted_files = $this->format();
    10. foreach($formatted_files as $file)
    11. {
    12. if ($file['error'] == 0 and is_uploaded_file($file['tmp_name']))
    13. {
    14. $target = $this->uploadDir.'/'.md5($file['name']).'.'.pathinfo($file['name'])['extension'];
    15. if (move_uploaded_file($file['tmp_name'], $target))
    16. {
    17. $uploadedFiles[] = [
    18. 'name'=>$file['name'],
    19. 'path'=>$target,
    20. 'size'=>$file['size'],
    21. ];
    22. }
    23. }
    24. }
    25. return $uploadedFiles;
    26. }
    27. // 创建上传目录
    28. private function makeDir(): bool
    29. {
    30. $path = 'dest/'.date('Y/m/d');
    31. $this->uploadDir = $path;
    32. return is_dir($path) or mkdir($path, 0755, true);
    33. }
    34. // 统一格式化文件
    35. private function format(): array
    36. {
    37. $files = [];
    38. foreach($_FILES as $file)
    39. {
    40. if(is_array($file['name'])) {
    41. foreach($file['name'] as $idx=>$value)
    42. {
    43. $files[] = [
    44. 'name'=>$file['name'][$idx],
    45. 'type'=>$file['type'][$idx],
    46. 'tmp_name'=>$file['tmp_name'][$idx],
    47. 'error'=>$file['error'][$idx],
    48. 'size'=>$file['size'][$idx]
    49. ];
    50. }
    51. } else {
    52. $files[] = $file;
    53. }
    54. }
    55. return $files;
    56. }
    57. }