PHP学习笔记 02 之文件上传
我们了解了表单传值后,这些我就可以完成PHP的文件上传了。我们了解PHP文件上传前,先了解PHP文件上传的原理。
一、PHP上传文件原理
- 第一步:将本地的文件通过form表单上传到服务器的临时目录中,临时目录是默认的,但我们可以修改,修改方式最后讲;
- 第二步:将上传的文件从临时目录中移动到指定目录中.。
二、form表单注意事项
- method属性必须是: method = ‘post’
- enctype属性必须是:enctype = multipart/form-data , 对上传文件进行编码,文件上传并不是上传的文件本身,而是上传文件的编码,由服务器端对编码进行分析。
三、简单的文件上传功能实现
1、思路分析


对于上面error字段的错误信息说明,php官方手册上给出了解释:
- UPLOAD_ERR_OK
- 其值为 0,没有错误发生,文件上传成功。
- UPLOAD_ERR_INI_SIZE
- 其值为 1,上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。
- UPLOAD_ERR_FORM_SIZE
- 其值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
- UPLOAD_ERR_PARTIAL
- 其值为 3,文件只有部分被上传。
- UPLOAD_ERR_NO_FILE
- 其值为 4,没有文件被上传。
- UPLOAD_ERR_NO_TMP_DIR
- 其值为 6,找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。
- UPLOAD_ERR_CANT_WRITE
- 其值为 7,文件写入失败。PHP 5.1.0 引进。
我们知道如何获取临时文件信息后,根据原理我们只需要做以下几件事就可以实现文件上传功能:
- 得到临时文件,即得到文件的路径,就是数组里的tmp_name;
- 自定义一个目录,然后加上文件名,然后拼接成文件路径,如‘E:/uploads/1.jpg’,我们上次的文件名就是数组里的name;
- 然后将临时文件移动到自定义的目录,这里我们会用到 move_uploaded_file 函数,关于这个函数如下说明:

2、代码实现
(1)前台test.html
<!--
Created by phpstrom
USER: 冷魅蘇
Date: 2019/4/27
Time: 17:00
-->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Examples</title>
</head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
<label for="myfile">上传文件:</label>
<input type="file" id="myfile" name="myfile">
<br>
<input type="submit" value="提交">
</form>
</body>
</html>
(2)后台upload.php
<?php
/*
* Created by phpstrom
* USER: 冷魅蘇
* Date: 2019/4/27
* Time: 17:02
*/
echo '<pre size="16">';
//得到临时文件
$tmpName = $_FILES['myfile']['tmp_name'];
//对应保存的目录
$fileName = 'E:/uploads/'. $_FILES['myfile']['name'];
//移动临时文件到目录
move_uploaded_file($tmpName,$fileName);
开心,文件上传已经实习了,但问题很大。
四、完善上传代码upload.php
1、简单的文件上传代码漏洞分析
上述的文件上传我们是已经实习了,但有几点问题:
- 自定义的文件目录是否存在,如果根本没有这个文件夹,会出现错误。所以,我们要检查是否有该文件夹,如果没有就创建。
- 文件上传到临时目录可能会出现错误,所以错误信息我们还是要显示出来的;
- 文件上传的大小要限制,不限制是不合理的,我们限制文件上传大小可以通过前台js限制,也可以通过php.ini中配置相应的参数(后面会说明),但我们还是要通过PHP代码进行判断;
- 我们常见的有头像上传、视频上传、文本上传等,所有我们对于不同的功能应该规定上传的文件类型;
- 我们保存的文件名不应该是同样的,否则每次上传就把原文件给覆盖了,但如何你需要把原文件给覆盖也可以,但生成不同的文件名保存,这个功能也应该是需要具备的;
- 临时文件的移动可能会出错,所以错误处理我们需要加上去;
- 文件保存的目录、文件上传的大小、上传的文件类型还有name的名称,这些我们都是可能变的,我们不可以固定不变,所以我们要把上面的全部封装成函数,以变量传参的方式来实习文件上传。
2、完善后的upload.php
下面直接给出修改后的代码,具体思路代码注释里面有说明:
<?php
/*
* Created by phpstrom
* USER: 冷魅蘇
* Date: 2019/4/25
* Time: 22:15
*/
/**
* @param $file 前台post提交的文件信息
* @param $mime 定义上传文件的类型
* @param $maxSize 定义上传文件的大小
* @param $path 定义保存的路径
* @return 返回上传成功的文件名或错误信息码
*/
function upload($file,$mime,$maxSize,$path){
//检查是否有该文件夹,如果没有就创建,并给予最高权限
if (!file_exists ($path)) {
if (!mkdir ("$path", 0777, true)) { //创建文件夹,没成功返回4010
return 4010;
}
}
//判断文件上传到临时目录的错误
switch ($file['error']){
case 1:
return 4001; //'上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值'
break;
case 2:
return 4002; //'上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值'
break;
case 3:
return 4003; //'文件上传不完整'
break;
case 4:
return 4004; //'没有文件被上传'
break;
case 6:
return 4005; //'服务器内部错误,文件写入失败'
break;
case 7:
return 4006; //'服务器内部错误,文件写入失败'
break;
}
if ($file['size']>$maxSize){
return 4007; //'文件上传大小超过限制'
}
//判断用户的上传文件的类型是合法,in_array() 数组查询
if (!in_array($file['type'],$mime)){
return 4008; //"上传文件必须是图片"
}
//得到临时文件名
$tmp = $file['tmp_name'];
//调用函数生成随机的文件名
$fileName = getRandFileName();
//获取文件的扩展名
$ext = pathinfo($file['name'],PATHINFO_EXTENSION);
//拼接成保存的文件名
$baseName = $fileName.'.'.$ext;
//拼接路径
$destination = $path.$baseName;
//如果文件合法,则将临时文件夹中的文件移动到指定的文件夹,并指定文件名
if (move_uploaded_file($tmp,$destination)){
return '上传成功,保存的文件名为:'.$baseName;
}else{
return 4009;
}
}
/**
* 随机文件名的格式,时间戳+随机6位的大小写字母和数字的组合
* mt_rand(x,y) x,y的随机整数
* chr 字符转换
* ASCII码表:97-122 小写字母 65-90大写字母
*/
function getRandFileName(){
//将时间戳转成我们想要的格式
$str = date('YmdHis',time());
for($i=0; $i<6; $i++){
switch (mt_rand(0,2)){ //随机从小写字母、大写字母、数字取一个
case 0:
$str .= chr(mt_rand(97,122));
break;
case 1:
$str .= chr(mt_rand(65,90));
break;
case 2:
$str .= mt_rand(0,9);
break;
}
}
return $str;
}
//文件上传信息手册
$errorInfo = [
'4001' => '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值',
'4002' => '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值',
'4003' => '文件上传不完整',
'4004' => '没有文件被上传',
'4005' => '服务器内部错误,文件写入失败',
'4006' => '服务器内部错误,文件写入失败',
'4007' => '文件上传大小超过限制',
'4008' => '上传文件必须是图片',
'4009' => '文件从临时文件夹移动到上传文件夹失败',
'4010' => '保存文件的目录创建失败,请确定目录是否合法'
];
//文件保存的文件夹
$path = 'E:/uploads/';
//定义文件上传的大小3MB
$maxSize = 1024*1024*3;
//定义允许用户上传的mime类型,现控制在图片上传
$mime = ['image/jpeg','image/jpg','image/pjpeg','image/png','image/gif'];
$file = $_FILES['myfile'];
$res = upload($file,$mime,$maxSize,$path);
echo '<pre style="font-size: 14px;">';
echo '<h3>临时文件上传信息</h3>';
var_dump($_FILES['myfile']);
echo '<h3>错误信息手册,显示文件名称上传成功</h3>';
var_dump($errorInfo);
echo $res;
说明:文件类型(MIME)

常见的几种类型:

欢喜,我们的文件上传功能就此完成。下面我们说明一下对于文件上传,php.ini的相关配置,php.ini文件就在你安装的php目录下。
五、php.ini相关参数
1. upload_tmp_dir //修改上传文件的临时目录
upload_max_filesize //上传允许的单文件的最大值
max_file_uploads //上传文件的允许最大数量

2. post_max_size //上传所有文件字节允许的最大值

声明:本文欢迎大家评论和转载,使用本文章或代码还请声明,且在使用处的明显位置给出。如有其它问题或有什么建议,可在下方评论,或加QQ(1414782205),或发邮箱jcdjor@163.com。
PHP学习笔记 02 之文件上传的更多相关文章
- [原创]java WEB学习笔记49:文件上传基础,基于表单的文件上传,使用fileuoload 组件
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- PHP学习笔记--文件目录操作(文件上传实例)
文件操作是每个语言必须有的,不仅仅局限于PHP,这里我们就仅用PHP进行讲解 php的文件高级操作和文件上传实例我放在文章的最后部分.--以后我还会给大家写一个PHP类似于网盘操作的例子 注意:阅读此 ...
- struts2学习笔记之十:文件上传
Struts2的上传 1.Struts2默认采用了apache commons-fileupload 2.Struts2支持三种类型的上传组件 3.需要引入commons-fileupload相关依赖 ...
- Kali学习笔记38:文件上传漏洞
早些年,提到Web渗透,或者搜索一些黑客教程 基本都会看到文件上传漏洞. 它是一个很经典的漏洞 但它本质其实不是一个漏洞,而是网站本身的上传文件功能 不过如果我们上传了Webshell,那么就成为了文 ...
- SpringMVC学习笔记八:文件上传下载(转)
转自:http://www.cnblogs.com/WJ-163/p/6269409.html 一.关键步骤 ①引入核心JAR文件 SpringMVC实现文件上传,需要再添加两个jar包.一个是文件上 ...
- SpringBoot学习笔记(8)-----SpringBoot文件上传
直接上代码,上传文件的前端页面: <body> <form action="/index/upload" enctype="multipart/form ...
- [原创]java WEB学习笔记50:文件上传案例
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- 【Java Web开发学习】Spring MVC文件上传
[Java Web开发学习]Spring MVC文件上传 转载:https://www.cnblogs.com/yangchongxing/p/9290489.html 文件上传有两种实现方式,都比较 ...
- (转载)JavaWeb学习总结(五十)——文件上传和下载
源地址:http://www.cnblogs.com/xdp-gacl/p/4200090.html 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传 ...
随机推荐
- 说一说js中__proto__和prototype以及原型继承的那些事
在面试中遇到过,问js如何实现继承,其实最好的方式就是构造函数+原型,今天在讨论中,发现自己以前理解上的一些误区,特地写出来,最近都比较忙,等手上的项目做完,可以来做个总结. 先说我以前没有认识到位的 ...
- vue学习之响应式原理的demo实现
Vue.js 核心: 1.响应式的数据绑定系统 2.组件系统. 访问器属性 访问器属性是对象中的一种特殊属性,它不能直接在对象中设置,而必须通过 defineProperty() 方法单独定义. va ...
- jQuery学习之旅 Item9 动画效果
1.元素的显示和隐藏 display:none; 隐藏 display:block; 显示 简单显示和隐藏方法 a) show() 显示 b) hide() 隐藏 c) toggle() 开关,显示则 ...
- 26.app后端怎么架设推送服务
推送服务已经是app的标配了.架设推送服务,除了可以使用第三方服务商外,也有大量的开源技术可以选择. 现在推送主要分两块,android推送和ios推送,在下面分别论述: 1. Android推 ...
- 玩转web之ligerui(一)---ligerGrid重新指定url
请珍惜小编劳动成果,该文章为小编原创,转载请注明出处. 在特定情况下,我们需要重新指定ligerGrid的url来获取不同的数据,在这里我说一下我用的方法: 首先先定义一个全局变量,然后定义liger ...
- 一次完整的HTTP网络请求过程详解
0. 前言 从我们在浏览器的地址栏输入http://blog.csdn.net/seu_calvin后回车,到我们看到该博客的主页,这中间经历了什么呢?简单地回答这个问题,大概是经历了域名解析.TC ...
- HashMap浅入理解
HashMap不能保证元素的顺序,HashMap能够将键设为null,也可以将值设为null,与之对应的是Hashtable,(注意大小写:不是HashTable),Hashtable不能将键和值设为 ...
- bzoj 1189 紧急疏散 网络流
二分答案,网络流判断 将每个门拆点,每个人连向每个门的dis~当前解 然后跑最大流,如果等于人数,即为可行解 #include<cstdio> #include<iostream&g ...
- Java 使用PDFBox提取PDF文件中的图片
今天做PDF文件解析,遇到一个需求:提取文件中的图片并保存.使用的是流行的apache开源jar包pdfbox, 但还是遇到坑了,比如pdfbox版本太高或太低都不能用!!这个包竟然没有很好地做好兼容 ...
- jenkins+docker 持续构建非docker in docker
工欲善其事必先利其器,为了解脱程序员的,我们程序员本身发明了很多好用的工具,通过各种工具的组合来达到我们想要的结果 本文采用jenkins docker svn maven作为相关工具,项目sprin ...