前言:安全问题
直接将文件上传到服务器是非常危险的行为,攻击者可以将病毒程序伪装成符合上传标准的文件,从而攻击服务器。服务器安全并不是本文提及的重点,但是该检查工具类所使用的原生函数都有对应的伪装破解方法,使用该工具类,并不能完全保证图片上传的安全,希望使用者务必记得这一点。
因此,此处推荐两种较为安全的方式。
前端通过API接口,直接将文件发至第三方云对象储存(例如腾讯云、阿里云、七牛等)
后端接受文件后执行基本检查,调用API或者使用SDK把文件发至第三方云对象储存。
注:该文章与程序不定时更新
调用基本说明
文件说明
— submit.html 示例前端文件,用于提交图片
— handle.php 示例后端文件,用于处理图片
— Image.php 实现图片检查与图片保存的工具类
— http.php 一个用于http报错的函数文件
使用说明
1.预定义常量:
需要用户预先定义以下常量:
FILE_PATH 上传到服务器的文件路径
UPLOAD_FILE_MAX_B 最大的图片大小
ALLOW_FILE_TYPES 允许的文件类型转化数组
示例如下:
//上传到服务器的文件路径
define('FILE_PATH', 'upload/');
//最大的图片大小
define('UPLOAD_FILE_MAX_B', 2 * 1024 * 1024);
//允许图片类型
define('ALLOW_FILE_TYPES', 'return array(
"image/png" => ".png",
"image/x-png" => ".png",
"image/jpeg" => ".jpg",
"image/pjpeg" => ".jpg"
);'
);
2.引入:
接着在处理图片的后端文件中需要引入该工具类与报错函数文件
require "./Image.php";
require "./http.php";
3.创建实例:
在try-catch块中创建该工具类的实例,并执行函数。执行函数需要用到的参数如下:
$inputName html文件里 上传文件的input框name属性值
$dir 上传的文件路径,根据具体情况进行调整,可以直接取FILE_PATH
示例代码如下:
try {
//html文件里 上传文件的input框name属性值
$inputName = 'file';
// 上传的文件路径 按日期分文件夹,方便日后的文件转移
$dir = FILE_PATH . date('Y/m') . '/';
$image = new \Image\Image($inputName);
// 图片检查
$image->check();
// 图片转移保存
$image->move($dir);
// 无异常
echo "图片保存成功";
} catch (\Exception $e) {
//http 报错
httpStatus($e->getCode());
//输出报错信息
echo $e->getMessage();
}
调用流程的详细说明
1. 上传图片的前端页面
在许多网页中,需要实现文件上传功能,最常见的是图片上传,前端html代码 submit.html 示例如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传图片页面</title>
</head>
<body>
<form action="handle.php" name="form" method="post" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit" name="submit" value="上传"/>
</form>
</body>
</html>
如果你对html不熟悉,你需要了解以下标签属性
<form>标签的enctype属性规定了在提交表单时要使用哪种内容类型。在表单需要二进制数据时,比如文件内容,请使用"multipart/form-data"。
<form>标签的method属性规定了在提交表单时使用的 HTTP请求方法,此处使用post方法。
<input>标签的type="file"属性规定了应该把输入作为文件来处理。举例来说,当在浏览器中预览时,会看到输入框旁边有一个浏览按钮。
<input>标签的name属性表示传输到后端的数据变量名,此处取值为”file“,并没有什么特殊含义,你喜欢的话也可以叫做 ”superImageFile“,只要和后端处理的变量名保持一致即可。
2.form表单传输的文件 & PHP 全局数组$_FILES的接收
form 表单会以”multipart/form-data” 形式,使用 HTTP 的 Post 方法,把数据发送到 handle.php 文件中。上传的文件数据在PHP的 $_FILES 变量里。
$_FILES 是一个全局数组,里面包含了上传文件的信息。
该示例中的 input name 为 “file”。(你喜欢的话也可以 把input name 都改成 ”superImageFile“)
通过使用 PHP 的全局数组 $_FILES,你可以从客户计算机向远程服务器上传文件。
第一个参数是表单的input name,第二个下标可填的参数如下所示:
$_FILES["file"]["name"]- 被上传文件名
$_FILES["file"]["type"]- 被上传文件的 MIME 类型,需要浏览器提供该信息的支持,例如”image/gif”。
$_FILES["file"]["size"] -被上传文件的大小,以字节计
$_FILES["file"]["tmp_name"]- 存储在服务器的文件的临时副本的名称(格式为:路径/文件名), 一般是系统默认。可以在php.ini里由upload_tmp_dir指定。
$_FILES["file"]["error"]- 由文件上传导致的错误代码,详情可参考PHP手册-特点-文件上传处理-错误信息说明
3.引入并调用 ImageCheck 工具类进行检查
在需要处理图片上传的后端文件中,引入以下两个文件。
require "./Image.php"; //Image 检查工具类
require "./http.php"; // http 报错函数文件
同时,需要预先定义好以下常量。
FILE_PATH 上传到服务器的文件路径
UPLOAD_FILE_MAX_B 最大的图片大小
ALLOW_FILE_TYPES 允许的文件类型转化数组
示例如下:
//上传到服务器的文件路径
define('FILE_PATH', 'upload/');
//最大的图片大小
define('UPLOAD_FILE_MAX_B', 2 * 1024 * 1024);
//允许图片类型
define('ALLOW_FILE_TYPES', 'return array(
"image/png" => ".png",
"image/x-png" => ".png",
"image/jpeg" => ".jpg",
"image/pjpeg" => ".jpg"
);'
);
Image 类通过抛出异常进行报错,因此需要在 try-catch 块中创建该工具类的实例,并执行函数。
抛出的异常,通过 http.php 内的函数 httpStatus() 进行内容的输出,并通过header来返回 http 状态。
创建 Image 实例,需要参数 $inputName, 表示的是form表单中 type=”file” 的<input> 标签 name 属性
try {
//html文件里 上传文件的input框name属性值
$inputName = 'file';
//创建实例
$image = new \Image\Image($inputName);
//执行函数
} catch ( \Exception $e) {
//http 报错
httpStatus($e->getCode());
//输出报错信息
echo $e->getMessage();
}
4.执行函数
Image 类实例化的对象,先使用 check() 函数进行图片检查。再使用 move() 函数移动图片到指定路径保存。
check() 函数不需要填入参数。
move() 函数需要填入变量$dir,表示上传的文件路径。
/** 进行基本的检查(空与异常),接着进行自定义的图片检查
* 检查完之后,会对该类的私有成员变量赋值
* $this -> fileTmpname 上传后的临时文件名称
* $this -> fileName 另存为的文件名,示例代码中文件名格式为 Ymd_His.后缀名
* 例如 20180313_151525.jpg
* @throws Exception
*/
public function check(){...}
/** 移动图片并保存
* @param $dir 保存文件的文件夹路径
* @param null $tmpname 上传后的临时文件名称(路径/文件名),默认取该类的私有成员变量值。
* @param null $filename 另存为的文件名,默认取该类的私有成员变量值。
* @throws Exception
*/
public function move($dir, $tmpname = null , $filename = null){...}
5.保存成功
若无报错异常,即图片检查无异常,并保存成功。
完整处理的示例代码 handle.php 如下
<?php
/**
* Created by PhpStorm.
* User: L
* Date: 2018-3-11
* Time: 17:19
*/
require "./Image.php";
require "./http.php";
//上传到服务器的文件路径
define('FILE_PATH', 'upload/');
//最大的图片大小
define('UPLOAD_FILE_MAX_B', 2 * 1024 * 1024);
//允许图片类型
define('ALLOW_FILE_TYPES', 'return array(
"image/png" => ".png",
"image/x-png" => ".png",
"image/jpeg" => ".jpg",
"image/pjpeg" => ".jpg"
);'
);
try {
//html文件里 上传文件的input框name属性值
$inputName = 'file';
//上传的文件路径 按日期分文件夹,方便日后的文件转移
$dir = FILE_PATH . date('Y/m') . '/';
//实例化对象
$image = new \Image\Image($inputName);
//执行图片检查
$image->check();
//执行图片转移并保存
$image->move($dir);
//无异常
echo "图片保存成功";
} catch (\Exception $e) {
//http 报错
httpStatus($e->getCode());
//输出报错信息
echo $e->getMessage();
}
955



被折叠的 条评论
为什么被折叠?



