# 文件上传
本篇主要介绍如何使用`ThinkPHP5`进行文件上传及验证。
- - [控制器定义](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/179236#u63A7u5236u5668u5B9Au4E49)
- [上传文件验证](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/179236#u4E0Au4F20u6587u4EF6u9A8Cu8BC1)
- [文件保存规则](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/179236#u6587u4EF6u4FDDu5B58u89C4u5219)
- [多文件上传](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/179236#u591Au6587u4EF6u4E0Au4F20)
- [后续文件操作](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/179236#u540Eu7EEDu6587u4EF6u64CDu4F5C)
## 控制器定义
> 文件上传使用ThinkPHP5内置的`think\File`类库,该类库可以轻松实现文件上传到本地服务器,如果需要上传到其它服务器或者平台,则需要后续调用其它类库或者接口。
首先来创建一个Upload控制器如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">controller</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Request</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Upload</span> <span class="hljs-keyword">extends</span> \<span class="hljs-title">think</span>\<span class="hljs-title">Controller</span></span>{
<span class="hljs-comment">// 文件上传表单</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->fetch();
}
<span class="hljs-comment">// 文件上传提交</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span><span class="hljs-number">(Request <span class="hljs-regexp">$request</span>)</span></span>{
<span class="hljs-comment">// 获取表单上传文件</span><span class="hljs-regexp">$file</span> = <span class="hljs-regexp">$request</span>->file(<span class="hljs-string">'file'</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">empty</span>(<span class="hljs-regexp">$file</span>)) {
<span class="hljs-regexp">$this</span>->error(<span class="hljs-string">'请选择上传文件'</span>);
}
<span class="hljs-comment">// 移动到框架应用根目录/public/uploads/ 目录下</span><span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->move(ROOT_PATH . <span class="hljs-string">'public'</span> . DS . <span class="hljs-string">'uploads'</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$info</span>) {
<span class="hljs-regexp">$this</span>->success(<span class="hljs-string">'文件上传成功:'</span> . <span class="hljs-regexp">$info</span>->getRealPath());
} <span class="hljs-keyword">else</span> {
<span class="hljs-comment">// 上传失败获取错误信息</span><span class="hljs-regexp">$this</span>->error(<span class="hljs-regexp">$file</span>->getError());
}
}
}</span>
```
```
然后创建模板文件(`application/index/view/upload/index.html`):
```
<pre class="calibre18">
```
<span class="hljs-regexp"><!doctype html></span><span class="hljs-regexp"><<span class="hljs-operator">html</span>></span><span class="hljs-regexp"><<span class="hljs-operator">head</span>></span><span class="hljs-regexp"><<span class="hljs-operator">meta</span> <span class="hljs-operator">charset</span>=<span class="hljs-string">"UTF-8"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">title</span>></span>文件上传示例<span class="hljs-regexp"></<span class="hljs-operator">title</span>></span><span class="hljs-regexp"><<span class="hljs-operator">style</span>></span><span class="css"><span class="hljs-regexp">body</span> <span class="hljs-operator">{
<span class="hljs-operator"><span class="hljs-title1">font-family</span>:<span class="hljs-string"><span class="hljs-operator">"Microsoft Yahei"</span>,<span class="hljs-operator">"Helvetica Neue"</span>,Helvetica,Arial,sans-serif</span></span>;
<span class="hljs-operator"><span class="hljs-title1">font-size</span>:<span class="hljs-string"><span class="hljs-number">16px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"><span class="hljs-number">5px</span></span></span>;
}</span><span class="hljs-regexp">.form</span><span class="hljs-operator">{
<span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">15px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">font-size</span>:<span class="hljs-string"> <span class="hljs-number">16px</span></span></span>;
}</span><span class="hljs-regexp">.form</span> <span class="hljs-regexp">.text</span> <span class="hljs-operator">{
<span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">3px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"><span class="hljs-number">2px</span> <span class="hljs-number">10px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">width</span>:<span class="hljs-string"> <span class="hljs-number">240px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">height</span>:<span class="hljs-string"> <span class="hljs-number">24px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">line-height</span>:<span class="hljs-string"> <span class="hljs-number">28px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">border</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#D4D4D4</span></span></span>;
}</span><span class="hljs-regexp">.form</span> <span class="hljs-regexp">.btn</span><span class="hljs-operator">{
<span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"><span class="hljs-number">6px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">6px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">width</span>:<span class="hljs-string"> <span class="hljs-number">120px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">font-size</span>:<span class="hljs-string"> <span class="hljs-number">16px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">border</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#D4D4D4</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">cursor</span>:<span class="hljs-string"> pointer</span></span>;
<span class="hljs-operator"><span class="hljs-title1">background</span>:<span class="hljs-string"><span class="hljs-title">#eee</span></span></span>;
}</span><span class="hljs-regexp">.form</span> <span class="hljs-regexp">.file</span><span class="hljs-operator">{
<span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"><span class="hljs-number">6px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">6px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">width</span>:<span class="hljs-string"> <span class="hljs-number">220px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">font-size</span>:<span class="hljs-string"> <span class="hljs-number">16px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">border</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#D4D4D4</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">cursor</span>:<span class="hljs-string"> pointer</span></span>;
<span class="hljs-operator"><span class="hljs-title1">background</span>:<span class="hljs-string"><span class="hljs-title">#eee</span></span></span>;
}</span><span class="hljs-regexp">a</span><span class="hljs-operator">{
<span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#868686</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">cursor</span>:<span class="hljs-string"> pointer</span></span>;
}</span><span class="hljs-operator"><span class="hljs-title1">a</span>:<span class="hljs-string">hover{
text-decoration: underline</span></span>;
}
<span class="hljs-regexp">h2</span><span class="hljs-operator">{
<span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#4288ce</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">font-weight</span>:<span class="hljs-string"> <span class="hljs-number">400</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">6px</span> <span class="hljs-number">0</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"> <span class="hljs-number">6px</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">font-size</span>:<span class="hljs-string"> <span class="hljs-number">28px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">border-bottom</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>;
}</span><span class="hljs-regexp">div</span><span class="hljs-operator">{
<span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"><span class="hljs-number">8px</span></span></span>;
}</span><span class="hljs-regexp">.info</span><span class="hljs-operator">{
<span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">12px</span> <span class="hljs-number">0</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">border-bottom</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>;
}</span><span class="hljs-regexp">.copyright</span><span class="hljs-operator">{
<span class="hljs-operator"><span class="hljs-title1">margin-top</span>:<span class="hljs-string"> <span class="hljs-number">24px</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">12px</span> <span class="hljs-number">0</span></span></span>;
<span class="hljs-operator"><span class="hljs-title1">border-top</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>;
}</span></span><span class="hljs-regexp"></<span class="hljs-operator">style</span>></span><span class="hljs-regexp"></<span class="hljs-operator">head</span>></span><span class="hljs-regexp"><<span class="hljs-operator">body</span>></span><span class="hljs-regexp"><<span class="hljs-operator">h2</span>></span>文件上传示例<span class="hljs-regexp"></<span class="hljs-operator">h2</span>></span><span class="hljs-regexp"><<span class="hljs-operator">FORM</span> <span class="hljs-operator">method</span>=<span class="hljs-string">"post"</span> <span class="hljs-operator">enctype</span>=<span class="hljs-string">"multipart/form-data"</span> <span class="hljs-operator">class</span>=<span class="hljs-string">"form"</span> <span class="hljs-operator">action</span>=<span class="hljs-string">"{:url('up')}"</span>></span>
选择文件:<span class="hljs-regexp"><<span class="hljs-operator">INPUT</span> <span class="hljs-operator">type</span>=<span class="hljs-string">"file"</span> <span class="hljs-operator">class</span>=<span class="hljs-string">"file"</span> <span class="hljs-operator">name</span>=<span class="hljs-string">"file"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">br</span>/></span><span class="hljs-regexp"><<span class="hljs-operator">INPUT</span> <span class="hljs-operator">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-operator">class</span>=<span class="hljs-string">"btn"</span> <span class="hljs-operator">value</span>=<span class="hljs-string">" 提交 "</span>></span><span class="hljs-regexp"></<span class="hljs-operator">FORM</span>></span><span class="hljs-regexp"><<span class="hljs-operator">div</span> <span class="hljs-operator">class</span>=<span class="hljs-string">"copyright"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">a</span> <span class="hljs-operator">title</span>=<span class="hljs-string">"官方网站"</span> <span class="hljs-operator">href</span>=<span class="hljs-string">"http://www.thinkphp.cn"</span>></span>ThinkPHP<span class="hljs-regexp"></<span class="hljs-operator">a</span>></span><span class="hljs-regexp"><<span class="hljs-operator">span</span>></span>V5<span class="hljs-regexp"></<span class="hljs-operator">span</span>></span><span class="hljs-regexp"><<span class="hljs-operator">span</span>></span>{ 十年磨一剑-为API开发设计的高性能框架 }<span class="hljs-regexp"></<span class="hljs-operator">span</span>></span><span class="hljs-regexp"></<span class="hljs-operator">div</span>></span><span class="hljs-regexp"></<span class="hljs-operator">body</span>></span><span class="hljs-regexp"></<span class="hljs-operator">html</span>></span>
```
```
访问下面的URL地址:
```
<pre class="calibre18">
```
<span class="hljs-string">http:</span>
<span class="hljs-comment">//tp5.com/index/upload</span>
```
```
![](https://img.kancloud.cn/ce/31/ce3161d1487d32532cff6af5505f3e1e_766x368.png)
如果没有选择任何文件点击提交的话,会显示:
![](https://img.kancloud.cn/23/fc/23fcea7b9f7a8b6fa836daebd8d36fc8_652x344.png)
选择文件后点击提交:
![](https://img.kancloud.cn/ed/82/ed82d381fdac150a1ca1710849d9777c_755x368.png)
![](https://img.kancloud.cn/0c/5d/0c5d787b74b375a9ee5e4a2d55e9e247_2110x443.png)
默认的上传文件会按照当前的日期自动保存
## 上传文件验证
可以在上传之前调用`validate`方法设置验证规则,例如:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 文件上传提交</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span><span class="hljs-number">(Request <span class="hljs-regexp">$request</span>)</span></span>{
<span class="hljs-comment">// 获取表单上传文件</span><span class="hljs-regexp">$file</span> = <span class="hljs-regexp">$request</span>->file(<span class="hljs-string">'file'</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">empty</span>(<span class="hljs-regexp">$file</span>)) {
<span class="hljs-regexp">$this</span>->error(<span class="hljs-string">'请选择上传文件'</span>);
}
<span class="hljs-comment">// 移动到框架应用根目录/public/uploads/ 目录下</span><span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->validate([<span class="hljs-string">'ext'</span> => <span class="hljs-string">'jpg,png'</span>])->move(ROOT_PATH . <span class="hljs-string">'public'</span> . DS . <span class="hljs-string">'uploads'</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$info</span>) {
<span class="hljs-regexp">$this</span>->success(<span class="hljs-string">'文件上传成功:'</span> . <span class="hljs-regexp">$info</span>->getRealPath());
} <span class="hljs-keyword">else</span> {
<span class="hljs-comment">// 上传失败获取错误信息</span><span class="hljs-regexp">$this</span>->error(<span class="hljs-regexp">$file</span>->getError());
}
}
```
```
`validate`方法设置了允许上传的文件后缀是jpg和png,当我们选择一个gif格式的文件后,会提示:
![](https://img.kancloud.cn/71/fd/71fdbee2d76ecc099f509da23f5cb479_664x346.png)
`validate`方法支持的验证规则包括:
验证规则 说明 参数类型 size 上传文件最大字节大小 integer ext 允许上传的文件后缀 数组或者字符串 type 允许上传的文件类型 数组或者字符串如果上传的文件后缀是图像格式的话,系统会自动检测是否为合法的图像文件,例如,我们创建一个hello.jpg文件,并且写入下列文本内容
```
<pre class="calibre18">
```
Hello,ThinkPHP5!
```
```
当我们上传该文件并且提交后显示:
![](https://img.kancloud.cn/e4/2c/e42c1280e5428ae518a6a487133632b7_687x336.png)
> 注意:文件上传验证用到了`exif`扩展,如果没有开启请自行开启。
如果你统一使用验证类`think\Validate`对表单进行验证,也可以直接使用控制器类`think\Controller`的`validate`方法进行上传文件验证,修改控制器up方法的代码为:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 文件上传提交</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span><span class="hljs-number">(Request <span class="hljs-regexp">$request</span>)</span></span>{
<span class="hljs-comment">// 获取表单上传文件</span><span class="hljs-regexp">$file</span> = <span class="hljs-regexp">$request</span>->file(<span class="hljs-string">'file'</span>);
<span class="hljs-comment">// 上传文件验证</span><span class="hljs-regexp">$result</span> = <span class="hljs-regexp">$this</span>->validate([<span class="hljs-string">'file'</span> => <span class="hljs-regexp">$file</span>], [<span class="hljs-string">'file'</span>=><span class="hljs-string">'require|image'</span>],[<span class="hljs-string">'file.require'</span> => <span class="hljs-string">'请选择上传文件'</span>, <span class="hljs-string">'file.image'</span> => <span class="hljs-string">'非法图像文件'</span>]);
<span class="hljs-keyword">if</span>(<span class="hljs-keyword">true</span> !== <span class="hljs-regexp">$result</span>){
<span class="hljs-regexp">$this</span>->error(<span class="hljs-regexp">$result</span>);
}
<span class="hljs-comment">// 移动到框架应用根目录/public/uploads/ 目录下</span><span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->move(ROOT_PATH . <span class="hljs-string">'public'</span> . DS . <span class="hljs-string">'uploads'</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$info</span>) {
<span class="hljs-regexp">$this</span>->success(<span class="hljs-string">'文件上传成功:'</span> . <span class="hljs-regexp">$info</span>->getRealPath());
} <span class="hljs-keyword">else</span> {
<span class="hljs-comment">// 上传失败获取错误信息</span><span class="hljs-regexp">$this</span>->error(<span class="hljs-regexp">$file</span>->getError());
}
}
```
```
关键的代码是这行:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 上传文件验证</span><span class="hljs-regexp">$result</span> = <span class="hljs-regexp">$this</span>->validate([<span class="hljs-string">'file'</span> => <span class="hljs-regexp">$file</span>], [<span class="hljs-string">'file'</span>=><span class="hljs-string">'require|image'</span>],[<span class="hljs-string">'file.require'</span> => <span class="hljs-string">'请选择上传文件'</span>, <span class="hljs-string">'file.image'</span> => <span class="hljs-string">'非法图像文件'</span>]);
```
```
由于设置了`require`验证规则(表示必须上传文件),所以如果没有选择任何文件直接提交的话,页面会提示:
![](https://img.kancloud.cn/23/fc/23fcea7b9f7a8b6fa836daebd8d36fc8_652x344.png)
`image`验证规则表示上传的必须是一个图像文件,如果选择上传了一个文本文件,页面会提示:
![](https://img.kancloud.cn/e4/2c/e42c1280e5428ae518a6a487133632b7_687x336.png)
如果需要上传一个100\*100的`PNG`图像文件,可以这样进行验证:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 上传文件验证</span><span class="hljs-regexp">$result</span> = <span class="hljs-regexp">$this</span>->validate([<span class="hljs-string">'file'</span> => <span class="hljs-regexp">$file</span>], [<span class="hljs-string">'file'</span>=><span class="hljs-string">'require|image:100,100,png'</span>],[<span class="hljs-string">'file.require'</span> => <span class="hljs-string">'请选择上传文件'</span>, <span class="hljs-string">'file.image'</span> => <span class="hljs-string">'必须是100*100的PNG格式文件'</span>]);
```
```
更多的上传文件验证规则还包括:
验证规则 说明 file 验证是否为File对象 image 验证是否为图像File对象 image:width,height\[,type\] 验证图像文件的类型和宽高 fileExt:zip,doc,... 验证文件后缀 fileMime:image/png,... 验证文件类型 fileSize:1024 验证文件大小## 文件保存规则
可以在上传之前调用`rule`方法设置上传文件的保存规则。
```
<pre class="calibre18">
```
<span class="hljs-comment">// 文件上传提交</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span><span class="hljs-number">(Request <span class="hljs-regexp">$request</span>)</span></span>{
<span class="hljs-comment">// 获取表单上传文件</span><span class="hljs-regexp">$file</span> = <span class="hljs-regexp">$request</span>->file(<span class="hljs-string">'file'</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">empty</span>(<span class="hljs-regexp">$file</span>)) {
<span class="hljs-regexp">$this</span>->error(<span class="hljs-string">'请选择上传文件'</span>);
}
<span class="hljs-comment">// 移动到框架应用根目录/public/uploads/ 目录下</span><span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->rule(<span class="hljs-string">'md5'</span>)->move(ROOT_PATH . <span class="hljs-string">'public'</span> . DS . <span class="hljs-string">'uploads'</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$info</span>) {
<span class="hljs-regexp">$this</span>->success(<span class="hljs-string">'文件上传成功:'</span> . <span class="hljs-regexp">$info</span>->getRealPath());
} <span class="hljs-keyword">else</span> {
<span class="hljs-comment">// 上传失败获取错误信息</span><span class="hljs-regexp">$this</span>->error(<span class="hljs-regexp">$file</span>->getError());
}
}
```
```
![](https://img.kancloud.cn/d7/73/d773392e52c76e74a8f84c496c9bf00b_1878x449.png)
系统默认提供了几种上传命名规则,包括:
规则 描述 date 根据日期和微秒数生成(默认规则) md5 对文件使用md5\_file散列生成 sha1 对文件使用sha1\_file散列生成> 其中md5和sha1规则会自动以散列值的前两个字符作为子目录,后面的散列值作为文件名。
如果需要自定义上传文件的保存规则,可以使用:
```
<pre class="calibre18">
```
/<span class="hljs-regexp">/ 移动到框架应用根目录/public</span><span class="hljs-regexp">/uploads/</span> 目录下
<span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->rule(<span class="hljs-string">'uniqid'</span>)->move(<span class="hljs-number">ROOT_PATH </span>. <span class="hljs-string">'public'</span> . <span class="hljs-number">DS </span>. <span class="hljs-string">'uploads'</span>);
```
```
这里使用了`uniqid`函数来生成唯一的ID命名上传文件,如果必要,还可以支持使用闭包定义规则,例如:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 移动到框架应用根目录/public/uploads/ 目录下</span><span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->rule(<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-number">(<span class="hljs-regexp">$file</span>)</span> </span>{
<span class="hljs-comment">// 使用自定义的文件保存规则</span><span class="hljs-keyword">return</span> <span class="hljs-regexp">$file</span>->getInfo(<span class="hljs-string">'type'</span>) . uniqid();
})->move(ROOT_PATH . <span class="hljs-string">'public'</span> . DS . <span class="hljs-string">'uploads'</span>);
```
```
![](https://img.kancloud.cn/2c/03/2c0365dfb97675352192f3bd8c583e54_1966x346.png)
如果希望指定某个文件的保存文件名,还可以直接使用:
```
<pre class="calibre18">
```
/<span class="hljs-regexp">/ 移动到框架应用根目录/public</span><span class="hljs-regexp">/uploads/</span> 目录下
<span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->move(<span class="hljs-number">ROOT_PATH </span>. <span class="hljs-string">'public'</span> . <span class="hljs-number">DS </span>. <span class="hljs-string">'uploads'</span>,<span class="hljs-string">'test'</span>);
```
```
![](https://img.kancloud.cn/79/da/79daee05a518766867466711b9c4f5e9_1369x353.png)
如果希望保持上传文件的原文件名保存,则可以使用
```
<pre class="calibre18">
```
/<span class="hljs-regexp">/ 移动到框架应用根目录/public</span><span class="hljs-regexp">/uploads/</span> 目录下
<span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->move(<span class="hljs-number">ROOT_PATH </span>. <span class="hljs-string">'public'</span> . <span class="hljs-number">DS </span>. <span class="hljs-string">'uploads'</span>,<span class="hljs-string">''</span>);
```
```
默认情况下,会覆盖服务器上传目录下的同名文件,如果不希望覆盖,可以使用:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 移动到服务器的上传目录 并且设置不覆盖</span><span class="hljs-regexp">$file</span>->move(ROOT_PATH . <span class="hljs-string">'public'</span> . DS . <span class="hljs-string">'uploads'</span>,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>);
```
```
如果要获取上传的保存文件名,可以调用返回对象的`getSaveName`方法:
```
<pre class="calibre18">
```
<span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->rule(<span class="hljs-string">'md5'</span>)->move(ROOT_PATH . <span class="hljs-string">'public'</span> . DS . <span class="hljs-string">'uploads'</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$info</span>) {
<span class="hljs-keyword">echo</span> <span class="hljs-regexp">$info</span>->getSaveName();
} <span class="hljs-keyword">else</span> {
<span class="hljs-regexp">$this</span>->error(<span class="hljs-regexp">$file</span>->getError());
}
```
```
## 多文件上传
如果你使用的是多文件上传表单,例如:
```
<pre class="calibre18">
```
<<span class="hljs-operator">FORM</span> method=<span class="hljs-string">"post"</span> enctype=<span class="hljs-string">"multipart/form-data"</span> <span class="hljs-operator"><span class="hljs-keyword">class</span>=</span><span class="hljs-string">"form"</span> action=<span class="hljs-string">"{:url('up')}"</span>>
<input <span class="hljs-operator"><span class="hljs-keyword">type</span>=</span><span class="hljs-string">"file"</span> name=<span class="hljs-string">"image[]"</span> /> <br>
<input <span class="hljs-operator"><span class="hljs-keyword">type</span>=</span><span class="hljs-string">"file"</span> name=<span class="hljs-string">"image[]"</span> /> <br>
<input <span class="hljs-operator"><span class="hljs-keyword">type</span>=</span><span class="hljs-string">"file"</span> name=<span class="hljs-string">"image[]"</span> /> <br>
<<span class="hljs-operator">INPUT</span> <span class="hljs-operator"><span class="hljs-keyword">type</span>=</span><span class="hljs-string">"submit"</span> <span class="hljs-operator"><span class="hljs-keyword">class</span>=</span><span class="hljs-string">"btn"</span> value=<span class="hljs-string">" 提交 "</span>>
</<span class="hljs-operator">FORM</span>>
```
```
控制器代码可以改成:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span><span class="hljs-number">(Request <span class="hljs-regexp">$request</span>)</span></span>{
<span class="hljs-comment">// 获取表单上传文件</span><span class="hljs-regexp">$files</span> = <span class="hljs-regexp">$request</span>->file(<span class="hljs-string">'image'</span>);
<span class="hljs-regexp">$item</span> = [];
<span class="hljs-keyword">foreach</span>(<span class="hljs-regexp">$files</span> <span class="hljs-keyword">as</span> <span class="hljs-regexp">$file</span>){
<span class="hljs-comment">// 移动到框架应用根目录/public/uploads/ 目录下</span><span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->move(ROOT_PATH . <span class="hljs-string">'public'</span> . DS . <span class="hljs-string">'uploads'</span>);
<span class="hljs-keyword">if</span>(<span class="hljs-regexp">$info</span>){
<span class="hljs-regexp">$item</span>[] = <span class="hljs-regexp">$info</span>->getRealPath();
}<span class="hljs-keyword">else</span>{
<span class="hljs-comment">// 上传失败获取错误信息</span><span class="hljs-regexp">$this</span>->error(<span class="hljs-regexp">$file</span>->getError());
}
}
<span class="hljs-regexp">$this</span>->success(<span class="hljs-string">'文件上传成功'</span>.implode(<span class="hljs-string">'<br/>'</span>,<span class="hljs-regexp">$item</span>));
}
```
```
## 后续文件操作
上传成功后返回的是`File`对象,除了可以使用`SplFileObject`的属性和方法之外,还可以使用File类自身提供的下列方法,便于进行后续的文件处理(例如对图像文件进行剪裁处理或者移动到远程服务器)。
方法 描述 getSaveName 获取保存的文件名(包含动态生成的目录) getInfo 获取上传文件信息 getMime 获取文件的MIME信息 md5 获取文件的md5散列值 sha1 获取文件的sha1散列值下面是一个简单的FTP文件移动的处理例子。
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span><span class="hljs-number">(Request <span class="hljs-regexp">$request</span>)</span></span>{
<span class="hljs-comment">// 获取表单上传文件</span><span class="hljs-regexp">$file</span> = <span class="hljs-regexp">$request</span>->file(<span class="hljs-string">'file'</span>);
<span class="hljs-comment">// 上传文件</span><span class="hljs-regexp">$info</span> = <span class="hljs-regexp">$file</span>->move(ROOT_PATH . <span class="hljs-string">'public'</span> . DS . <span class="hljs-string">'uploads'</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$info</span>) {
<span class="hljs-comment">// 移动文件到FTP服务器</span><span class="hljs-regexp">$link</span> = ftp_connect(<span class="hljs-string">'212.45.5.78'</span>);
ftp_login(<span class="hljs-regexp">$link</span>, <span class="hljs-string">'root'</span>, <span class="hljs-string">'password'</span>);
<span class="hljs-comment">/* 移动文件 */</span><span class="hljs-regexp">$path</span> = ftp_pwd(<span class="hljs-regexp">$link</span>) . <span class="hljs-string">'/uploads/'</span>;
<span class="hljs-keyword">if</span> (!ftp_put(<span class="hljs-regexp">$link</span>, <span class="hljs-regexp">$path</span>.<span class="hljs-regexp">$info</span>->getFilename(), <span class="hljs-regexp">$info</span>->getRealPath(), FTP_BINARY)) {
<span class="hljs-regexp">$this</span>->error(<span class="hljs-string">'文件上传保存错误!'</span>);
}
} <span class="hljs-keyword">else</span> {
<span class="hljs-comment">// 上传失败获取错误信息</span><span class="hljs-regexp">$this</span>->error(<span class="hljs-regexp">$file</span>->getError());
}
}
```
```
还可以对上传的文件进行处理,后面我们还会讲到对上传图像文件进行额外的图像处理。
- 脕茫隆垄脨貌脩脭
- 脕茫隆垄脨貌脩脭
- 脪禄隆垄禄霉麓隆
- 脪禄隆垄禄霉麓隆
- 露镁隆垄URL潞脥脗路脫脡
- 露镁隆垄URL潞脥脗路脫脡
- 脠媒隆垄脟毛脟贸潞脥脧矛脫娄
- 脠媒隆垄脟毛脟贸潞脥脧矛脫娄
- 脣脛隆垄脢媒戮脻驴芒
- 脣脛隆垄脢媒戮脻驴芒
- 脦氓隆垄虏茅脩炉脫茂脩脭
- 脦氓隆垄虏茅脩炉脫茂脩脭
- 脕霉隆垄脛拢脨脥潞脥鹿脴脕陋
- 拢篓1拢漏脛拢脨脥露篓脪氓
- 拢篓2拢漏禄霉麓隆虏脵脳梅
- 拢篓3拢漏露脕脠隆脝梅潞脥脨脼赂脛脝梅
- 拢篓4拢漏脌脿脨脥脳陋禄禄潞脥脳脭露炉脥锚鲁脡
- 拢篓5拢漏虏茅脩炉路露脦搂
- 拢篓6拢漏脢盲脠毛潞脥脩茅脰陇
- 拢篓7拢漏鹿脴脕陋
- 拢篓8拢漏脛拢脨脥脢盲鲁枚
- 脝脽隆垄脢脫脥录潞脥脛拢掳氓
- 脝脽隆垄脢脫脥录潞脥脛拢掳氓
- 掳脣隆垄碌梅脢脭潞脥脠脮脰戮
- 掳脣隆垄碌梅脢脭潞脥脠脮脰戮
- 戮脜隆垄API驴陋路垄
- 戮脜隆垄API驴陋路垄
- 脢庐隆垄脙眉脕卯脨脨鹿陇戮脽
- 脢庐隆垄脙眉脕卯脨脨鹿陇戮脽
- 脢庐脪禄隆垄脌漏脮鹿
- 脢庐脪禄隆垄脌漏脮鹿
- 脢庐露镁隆垄脭脫脧卯
- Cookie
- Session
- 碌楼脭陋虏芒脢脭
- 脥录脧帽麓娄脌铆
- 脦脛录镁脡脧麓芦
- 脩茅脰陇脗毛
- 赂陆脗录
- A隆垄鲁拢录没脦脢脤芒录炉
- B隆垄3.2潞脥5.0脟酶卤冒
- C隆垄脰煤脢脰潞炉脢媒
- 路卢脥芒脝陋拢潞脩搂脧掳ThinkPHP5碌脛脮媒脠路脳脣脢脝
- 路卢脥芒脝陋拢潞脩搂脧掳ThinkPHP5碌脛脮媒脠路脳脣脢脝