博客列表 >PHP - 文件上传实例

PHP - 文件上传实例

晴天
晴天原创
2020年05月12日 18:08:09802浏览

文件上传演示地址http://php.rc238.cn/0511

文件上传

1. 文件上传配置

文件上传项目项在php.ini中设置,常用的配置项有:

序号 配置项 默认值 描述
1 file_uploads On 使 PHP 支持文件上传
2 upload_tmp_dir /tmp 指示应该临时把上传的文件存储在什么位置
3 max_file_uploads 20 单次请求时允许上传的最大文件数量
4 max_execution_time 30 设置 PHP 最长执行时间(秒)
5 max_input_time 60 设置 PHP 通过 POST/GET/PUT 接收数据的时长(秒)
6 memory_limit 128M 系统分配给当前脚本执行可用的最大内存容量
7 post_max_size 8M 允许的 POST 数据的总大小(以字节为单位)
8 upload_max_filesize 32M 允许的尽可能最大的文件上传(以字节为单位)

$_FILES

  • 上传文件的描述信息,全部保存在系统全局变量$_FILES
  • $_FILES以二维数组形式保存: $_FILES['form_file_name']['key']
  • 'form_file_name': 对应着表单中<input type="file" name="my_pic">name属性值
  • 'key': 共有 5 个键名, 描述如下:
序号 键名 描述
1 name 文件在客户端的原始文件名(即存在用户电脑上的文件名)
2 type 文件的 MIME 类型, 由浏览器提供, PHP 并不检查它
3 tmp_name 文件被上传到服务器上之后,在临时目录中临时文件名
4 error 和该文件上传相关的错误代码
5 size 已上传文件的大小(单位为字节)
  • 文件上传错误信息描述
序号 常量 描述
1 UPLOAD_ERR_OK 0 没有错误发生,文件上传成功
2 UPLOAD_ERR_INI_SIZE 1 文件超过php.iniupload_max_filesize
3 UPLOAD_ERR_FORM_SIZE 2 文件大小超过表单中MAX_FILE_SIZE指定的值
4 UPLOAD_ERR_PARTIAL 3 文件只有部分被上传
5 UPLOAD_ERR_NO_FILE 4 没有文件被上传
6 UPLOAD_ERR_NO_TMP_DIR 6 找不到临时文件夹
7 UPLOAD_ERR_CANT_WRITE 7 文件写入失败
  • 支持文件上传的前端表单设置
序号 属性设置 描述
1 <form method="POST"> 请求类型必须是POST
2 <form enctype="multipart/form-data"> 设置表单提交数据的编码类型
3 <input type="file" name="uploads"> 设置表单控件类型与名称以支持上传
4 <input type="hidden" name="MAX_FILE_SIZE" value="..."> 设置隐藏域限制上传文件大小(可选)
  • [扩展] enctype属性说明

enctype: 设置表单数据,在发送到服务器之前的编码规则

序号 属性值 描述
1 application/x-www-form-urlencoded 默认值, 发送前进行编码,空格转+,非空字符转 16 进制
2 multipart/form-data 不对字符编码,以二进制发送,适合文件上传
3 text/plain 纯文本发送,仅对空格编码(转为+)

4. MIME 类型

4.1 概述

  • MIME: (Multipurpose Internet Mail Extensions)的简写,中文意思”多功能因特网邮件扩展”
  • MIME: 最初用来表示 Email 附件格式的字符串, 后来演变成为网络文档或应用程序的文档格式规范
  • MIME: 由一个媒体类型一个子类组成, 中间用斜线/分隔,例如text/css

4.2 类型

序号 类型 描述 示例
1 text 文本 text/plain,text/html,text/css,text/javascript
2 image 图像 1 image/jpeg,image/gif,image/png,image/bmp,image/ webp,
2 image 图像 2 image/x-icon, image/vnd.microsoft.icon
3 audio 音频 audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav
4 video 视频 video/mp4,video/mpeg,video/webm, video/ogg,video/x-msvideo
5 application 二进制 1 application/octet-stream, application/javascript, application/ecmascript
5 application 二进制 2 application/json,application/pkcs12, application/vnd.mspowerpoint
5 application 二进制 3 application/xhtml+xml, application/xml, application/pdf,application/x-gzip
  • 表中,以x-为前缀的是还没有成为国际标准的格式
  • 如果某个文档不在该列表中,会识别为: applicaton/octet-stream, 如.md文档, 尽管它是纯文本

演示代码

html 部分

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <link rel="stylesheet" href="index.css" />
  7. <title>单文件上传</title>
  8. </head>
  9. <body>
  10. <img src="http://pic1.win4000.com/wallpaper/e/57bff123d2e05.jpg" alt="" />
  11. <section>
  12. <form action="?mode=single" method="post" enctype="multipart/form-data">
  13. <fieldset>
  14. <legend>单文件上传</legend>
  15. <input type="file" name="my_pic" />
  16. <button>上传</button>
  17. </fieldset>
  18. </form>
  19. <form action="?mode=multiple" method="post" enctype="multipart/form-data">
  20. <fieldset>
  21. <legend>多文件上传</legend>
  22. <input type="file" name="my_pic1" required />
  23. <input type="file" name="my_pic2" required />
  24. <input type="file" name="my_pic3" required />
  25. <button>上传</button>
  26. </fieldset>
  27. </form>
  28. <form action="?mode=batch" method="post" enctype="multipart/form-data">
  29. <fieldset>
  30. <legend>批量上传</legend>
  31. <input type="file" name="my_pic[]" multiple required />
  32. <button>上传</button>
  33. </fieldset>
  34. </form>
  35. </section>
  36. <section>
  37. <?php
  38. require 'handle.php';
  39. ?>
  40. </section>
  41. </body>
  42. </html>

css 部分

  1. * {
  2. margin: 0px;
  3. padding: 0px;
  4. box-sizing: border-box;
  5. }
  6. body {
  7. min-height: 100vh;
  8. min-width: 100vw;
  9. }
  10. body > img {
  11. position: fixed;
  12. top: 0;
  13. left: 0;
  14. z-index: -1;
  15. width: 100%;
  16. height: 100%;
  17. }
  18. section:first-of-type {
  19. background-color: #fff;
  20. width: 800px;
  21. margin: 50px auto 0px;
  22. padding: 20px;
  23. opacity: 0.7;
  24. }
  25. fieldset {
  26. border: 1px solid #ccc;
  27. text-align: center;
  28. padding: 20px 0px;
  29. }
  30. legend {
  31. color: green;
  32. margin: auto;
  33. }
  34. fieldset > input {
  35. border: none;
  36. padding: 5px;
  37. color: lime;
  38. width: 120px;
  39. }
  40. fieldset > button {
  41. width: 60px;
  42. height: 25px;
  43. border: none;
  44. border-radius: 10px;
  45. background-color: lightskyblue;
  46. }
  47. fieldset > button:hover {
  48. background-color: magenta;
  49. }
  50. section:last-of-type > div {
  51. width: 800px;
  52. margin: 20px auto;
  53. display: flex;
  54. flex-flow: row nowrap;
  55. background-color: lightgrey;
  56. padding: 10px;
  57. border-radius: 10px;
  58. }
  59. section:last-of-type > div > img {
  60. width: 80px;
  61. margin-right: 20px;
  62. }

php 部分

  1. <?php
  2. //创建一个异常类 抛出异常
  3. class FileException extends Exception
  4. {
  5. public
  6. function __toString()
  7. {
  8. return <<< AAA
  9. <script>
  10. alert('{$this->message}');
  11. </script>
  12. AAA;
  13. }
  14. }
  15. try {
  16. //创建类 把方式,文件名传进去处理
  17. class FileHandle
  18. {
  19. // 接收数据
  20. public function __construct($Tmp_FileName, $DestFileName, $fileType, $i)
  21. {
  22. $this->set($Tmp_FileName, $DestFileName, $fileType, $i);
  23. }
  24. //创建保存文件方法
  25. public function set($Tmp_FileName, $DestFileName, $fileType, $i)
  26. {
  27. if ($fileType === 'image') {
  28. if (move_uploaded_file($Tmp_FileName, $DestFileName)) {
  29. echo "<div><img src='{$DestFileName}' width='200'>";
  30. echo '<p>文件上传成功</p></div>';
  31. }
  32. } else {
  33. $err = '第' . $i . '个文件类型错误,终止上传';
  34. throw new FileException($err);
  35. }
  36. }
  37. }
  38. //创建变量
  39. //文件异常码
  40. $errorcode = '';
  41. //文件类型 image/jpge 切割一下只要前面的image
  42. $fileType = '';
  43. //原始文件名
  44. $OriginalFileName = '';
  45. //临时文件名
  46. $Tmp_FileName = '';
  47. // 目录文件名 加密一下
  48. $DestFileName = '';
  49. //赋值 如果是get才执行
  50. if ($_GET) {
  51. // 获取当前上传方式 ?mode = 单文件single 多文件 multiple 批量 batch
  52. $mode = strtolower($_GET['mode']);
  53. $i = 1;
  54. // 判断get值
  55. switch ($mode) {
  56. ### get=single
  57. case 'single':
  58. $errorcode = $_FILES['my_pic']['error'];
  59. $fileType = strstr($_FILES['my_pic']['type'], '/', true);
  60. $OriginalFileName = $_FILES['my_pic']['name'];
  61. $Tmp_FileName = $_FILES['my_pic']['tmp_name'];
  62. $DestFileName = 'uploads/' . md5(sha1(time() . mt_rand(1, 1000))) . strstr($OriginalFileName, '.');
  63. if (is_uploaded_file($Tmp_FileName)) {
  64. // 执行类实例
  65. new FileHandle($Tmp_FileName, $DestFileName, $fileType, $i);
  66. }
  67. break;
  68. ### get=multiple
  69. case 'multiple':
  70. // 遍历数组 每个子数组给别名$file
  71. foreach ($_FILES as $file) {
  72. $errorcode = $file['error'];
  73. $fileType = strstr($file['type'], '/', true);
  74. $OriginalFileName = $file['name'];
  75. $Tmp_FileName = $file['tmp_name'];
  76. $DestFileName = 'uploads/' . md5(sha1(time() . mt_rand(1, 1000))) . strstr($OriginalFileName, '.');
  77. if (is_uploaded_file($Tmp_FileName)) {
  78. // 执行类实例
  79. new FileHandle($Tmp_FileName, $DestFileName, $fileType, $i++);
  80. }
  81. }
  82. break;
  83. ### get=batch
  84. case 'batch':
  85. if ($_FILES['my_pic']) {
  86. foreach ($_FILES['my_pic']['error'] as $key => $error) {
  87. if ($error === 0) {
  88. $errorcode = $_FILES['my_pic']['error'][$key];
  89. $fileType = strstr($_FILES['my_pic']['type'][$key], '/', true);
  90. $OriginalFileName = $_FILES['my_pic']['name'][$key];;
  91. $Tmp_FileName = $_FILES['my_pic']['tmp_name'][$key];
  92. $DestFileName = 'uploads/' . md5(sha1(time() . mt_rand(1, 1000))) . strstr($OriginalFileName, '.');
  93. if (is_uploaded_file($Tmp_FileName)) {
  94. // 执行类实例
  95. new FileHandle($Tmp_FileName, $DestFileName, $fileType, $i++);
  96. }
  97. }
  98. }
  99. }
  100. break;
  101. default:
  102. echo <<< BBB
  103. <script>
  104. alert('非法的参数请求');
  105. location.href='index.php';
  106. </script>
  107. BBB;
  108. }
  109. }
  110. if ($errorcode > 0) {
  111. switch ($errorcode) {
  112. case 1:
  113. throw new FileException('上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值', 1);
  114. break;
  115. case 2:
  116. throw new FileException('上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值', 2);
  117. break;
  118. case 3:
  119. throw new FileException('文件只有部分被上传', 3);
  120. break;
  121. case 4:
  122. throw new FileException('当前没有文件被上传', 4);
  123. break;
  124. case 6:
  125. throw new FileException('找不到临时文件夹', 6);
  126. break;
  127. case 7:
  128. throw new FileException('文件写入失败', 8);
  129. break;
  130. default:
  131. throw new FileException('未知错误', 10);
  132. }
  133. }
  134. } catch (FileException $e) {
  135. echo $e;
  136. }
  137. ?>

总结

写个这个忙活一天,代码删了写 写了删 写到最后又感觉前面有些代码冗余 又重构,还是经验不足,要多敲敲代码了

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议