## 上傳表單
在ThinkPHP中使用上傳功能無需進行特別處理。例如,下面是一個帶有附件上傳的表單提交:
~~~
<form action="__URL__/upload" enctype="multipart/form-data" method="post" >
<input type="text" name="name" />
<input type="file" name="photo" />
<input type="submit" value="提交" >
</form>
~~~
> 注意,要使用上傳功能 你的表單需要設置 enctype="multipart/form-data"
### 多文件上傳支持
如果需要使用多個文件上傳,只需要修改表單,把
~~~
<input type='file' name='photo'>
~~~
改為
~~~
<input type='file' name='photo1'>
<input type='file' name='photo2'>
<input type='file' name='photo3'>
~~~
或者
~~~
<input type='file' name='photo[]'>
<input type='file' name='photo[]'>
<input type='file' name='photo[]'>
~~~
兩種方式的多附件上傳系統的文件上傳類都可以自動識別。
## 上傳操作
ThinkPHP文件上傳操作使用`Think\Upload`類,假設前面的表單提交到當前控制器的upload方法,我們來看下upload方法的實現代碼:
~~~
public function upload(){
$upload = new \Think\Upload();// 實例化上傳類
$upload->maxSize = 3145728 ;// 設置附件上傳大小
$upload->exts = array('jpg', 'gif', 'png', 'jpeg');// 設置附件上傳類型
$upload->rootPath = './Uploads/'; // 設置附件上傳根目錄
$upload->savePath = ''; // 設置附件上傳(子)目錄
// 上傳文件
$info = $upload->upload();
if(!$info) {// 上傳錯誤提示錯誤信息
$this->error($upload->getError());
}else{// 上傳成功
$this->success('上傳成功!');
}
}
~~~
> 上傳類對圖片文件的上傳安全做了支持,如果企圖上傳非法的圖像文件,系統會提示 `非法圖像文件`。 為了更好的使用上傳功能,建議你的服務器開啟`finfo`模塊支持
## 上傳參數
在上傳操作之前,我們可以對上傳的屬性進行一些設置,Upload類支持的屬性設置包括:
| 屬性 | 描述 |
|-----|-----|
| maxSize | 文件上傳的最大文件大小(以字節為單位),0為不限大小 |
| rootPath | 文件上傳保存的根路徑 |
| savePath | 文件上傳的保存路徑(相對于根路徑) |
| saveName | 上傳文件的保存規則,支持數組和字符串方式定義 |
| saveExt | 上傳文件的保存后綴,不設置的話使用原文件后綴 |
| replace | 存在同名文件是否是覆蓋,默認為false |
| exts | 允許上傳的文件后綴(留空為不限制),使用數組或者逗號分隔的字符串設置,默認為空 |
| mimes | 允許上傳的文件類型(留空為不限制),使用數組或者逗號分隔的字符串設置,默認為空 |
| autoSub | 自動使用子目錄保存上傳文件 默認為true |
| subName | 子目錄創建方式,采用數組或者字符串方式定義 |
| hash | 是否生成文件的hash編碼 默認為true |
| callback | 檢測文件是否存在回調,如果存在返回文件信息數組 |
上面的屬性可以通過兩種方式傳入:
### 實例化傳入
我們可以在實例化的時候直接傳入參數數組,例如:
~~~
$config = array(
'maxSize' => 3145728,
'rootPath' => './Uploads/',
'savePath' => '',
'saveName' => array('uniqid',''),
'exts' => array('jpg', 'gif', 'png', 'jpeg'),
'autoSub' => true,
'subName' => array('date','Ymd'),
);
$upload = new \Think\Upload($config);// 實例化上傳類
~~~
> 關于saveName和subName的使用后面我們會有詳細的描述。
### 動態賦值
支持在實例化后動態賦值上傳參數,例如:
~~~
$upload = new \Think\Upload();// 實例化上傳類
$upload->maxSize = 3145728;
$upload->rootPath = './Uploads/';
$upload->savePath = '';
$upload->saveName = array('uniqid','');
$upload->exts = array('jpg', 'gif', 'png', 'jpeg');
$upload->autoSub = true;
$upload->subName = array('date','Ymd');
~~~
上面的設置和實例化傳入的效果是一致的。
## 上傳文件信息
設置好上傳的參數后,就可以調用`Think\Upload`類的upload方法進行附件上傳,如果失敗,返回false,并且用getError方法獲取錯誤提示信息;如果上傳成功,就返回成功上傳的文件信息數組。
~~~
$upload = new \Think\Upload();// 實例化上傳類
$upload->maxSize = 3145728 ;// 設置附件上傳大小
$upload->exts = array('jpg', 'gif', 'png', 'jpeg');// 設置附件上傳類型
$upload->rootPath = './Uploads/'; // 設置附件上傳根目錄
$upload->savePath = ''; // 設置附件上傳(子)目錄
// 上傳文件
$info = $upload->upload();
if(!$info) {// 上傳錯誤提示錯誤信息
$this->error($upload->getError());
}else{// 上傳成功 獲取上傳文件信息
foreach($info as $file){
echo $file['savepath'].$file['savename'];
}
}
~~~
每個文件信息又是一個記錄了下面信息的數組,包括:
| 屬性 | 描述 |
|-----|-----|
| key | 附件上傳的表單名稱 |
| savepath | 上傳文件的保存路徑 |
| name | 上傳文件的原始名稱 |
| savename | 上傳文件的保存名稱 |
| size | 上傳文件的大小 |
| type | 上傳文件的MIME類型 |
| ext | 上傳文件的后綴類型 |
| md5 | 上傳文件的md5哈希驗證字符串 僅當hash設置開啟后有效 |
| sha1 | 上傳文件的sha1哈希驗證字符串 僅當hash設置開啟后有效 |
文件上傳成功后,就可以使用這些文件信息來進行其他的數據操作,例如保存到當前數據表或者單獨的附件數據表。
例如,下面表示把上傳信息保存到數據表的字段:
~~~
$model = M('Photo');
// 取得成功上傳的文件信息
$info = $upload->upload();
// 保存當前數據對象
$data['photo'] = $info['photo']['savename'];
$data['create_time'] = NOW_TIME;
$model->add($data);
~~~
## 單文件上傳
upload方法支持多文件上傳,有時候,我們只需要上傳一個文件,就可以使用Upload類提供的**uploadOne**方法上傳單個文件,例如:
~~~
public function upload(){
$upload = new \Think\Upload();// 實例化上傳類
$upload->maxSize = 3145728 ;// 設置附件上傳大小
$upload->exts = array('jpg', 'gif', 'png', 'jpeg');// 設置附件上傳類型
$upload->rootPath = './Uploads/'; // 設置附件上傳根目錄
// 上傳單個文件
$info = $upload->uploadOne($_FILES['photo1']);
if(!$info) {// 上傳錯誤提示錯誤信息
$this->error($upload->getError());
}else{// 上傳成功 獲取上傳文件信息
echo $info['savepath'].$info['savename'];
}
}
~~~
> uploadOne方法上傳成功后返回的文件信息和upload方法的區別是只有單個文件信息的一維數組。
## 上傳文件的命名規則
上傳文件的命名規則(saveName)用于確保文件不會產生沖突或者覆蓋的情況。命名規則的定義可以根據你的業務邏輯來調整,不是固定的。例如,如果你采用時間戳的方式來定義命名規范,那么在同時上傳多個文件的時候可能產生沖突(因為同一秒內可以上傳多個文件),因此你需要根據你的業務需求來設置合適的上傳命名規則。這里順便來說下saveName參數的具體用法。
### 采用函數方式
如果傳入的字符串是一個函數名,那么表示采用函數動態生成上傳文件名(不包括文件后綴),例如:
~~~
// 采用時間戳命名
$upload->saveName = 'time';
// 采用GUID序列命名
$upload->saveName = 'com_create_guid';
~~~
也可以采用用戶自定義函數
~~~
// 采用自定義函數命名
$upload->saveName = 'myfun';
~~~
> 默認的命名規則設置是采用uniqid函數生成一個唯一的字符串序列。
saveName的值支持數組和字符串兩種方式,如果是只有一個參數或者沒有參數的函數,直接使用字符串設置即可,如果需要傳入額外的參數,可以使用數組方式,例如:
~~~
// 采用date函數生成命名規則 傳入Y-m-d參數
$upload->saveName = array('date','Y-m-d');
// 如果有多個參數需要傳入的話 可以使用數組
$upload->saveName = array('myFun',array('__FILE__','val1','val2'));
~~~
如果需要使用上傳的原始文件名,可以采用**__FILE__**傳入,所以上面的定義規則,最終的結果是 `myFun('上傳文件名','val1','val2')`執行的結果。
### 直接設置上傳文件名
如果傳入的參數不是一個函數名,那么就會直接當做是上傳文件名,例如:
~~~
$upload->saveName = time().'_'.mt_rand();
~~~
表示上傳的文件命名采用時間戳加一個隨機數的組合字符串方式。
當然,如果覺得有必要,你還可以固定設置一個上傳文件的命名規則,用于固定保存某個上傳文件。
~~~
$upload->saveName = 'ThinkPHP';
~~~
### 保持上傳文件名不變
如果你想保持上傳的文件名不變,那么只需要設置命名規范為空即可,例如:
~~~
$upload->saveName = '';
~~~
> 一般來說不建議保持不變,因為會導致相同的文件名上傳后被覆蓋的情況。
## 子目錄保存
saveName只是用于設置文件的保存規則,不涉及到目錄,如果希望對上傳的文件分子目錄保存,可以設置`autoSub`和`subName`參數來完成,例如:
~~~
// 開啟子目錄保存 并以日期(格式為Ymd)為子目錄
$upload->autoSub = true;
$upload->subName = array('date','Ymd');
~~~
可以使用自定義函數來保存,例如:
~~~
// 開啟子目錄保存 并調用自定義函數get_user_id生成子目錄
$upload->autoSub = true;
$upload->subName = 'get_user_id';
~~~
和saveName參數一樣,subName的定義可以采用數組和字符串的方式。
> 注意:如果get_user_id函數未定義的話,會直接以get_user_id字符串作為子目錄的名稱保存。
子目錄保存和文件命名規則可以結合使用。
## 上傳驅動
上傳類可以支持不同的環境,通過相應的上傳驅動來解決,默認情況下使用本地(Local)上傳驅動,當然,你還可以設置當前默認的上傳驅動類型,例如:
~~~
'FILE_UPLOAD_TYPE' => 'Ftp',
'UPLOAD_TYPE_CONFIG' => array(
'host' => '192.168.1.200', //服務器
'port' => 21, //端口
'timeout' => 90, //超時時間
'username' => 'ftp_user', //用戶名
'password' => 'ftp_pwd', //密碼 ),
~~~
表示當前使用Ftp作為上傳類的驅動,上傳的文件會通過FTP傳到指定的遠程服務器。
也可以在實例化上傳類的時候指定,例如:
~~~
$config = array(
'maxSize' = 3145728,
'rootPath' = './Uploads/',
'savePath' = '',
'saveName' = array('uniqid',''),
'exts' = array('jpg', 'gif', 'png', 'jpeg'),
'autoSub' = true,
'subName' = array('date','Ymd'),
);
$ftpConfig = array(
'host' => '192.168.1.200', //服務器
'port' => 21, //端口
'timeout' => 90, //超時時間
'username' => 'ftp_user', //用戶名
'password' => 'ftp_pwd', //密碼 );
$upload = new \Think\Upload($config,'Ftp',$ftpConfig);// 實例化上傳類
~~~
> 目前已經支持的上傳驅動包括Local、Ftp、Sae、Bcs、七牛和又拍云等。
- 序言
- 基礎
- 獲取ThinkPHP
- 環境要求
- 目錄結構
- 入口文件
- 自動生成
- 模塊
- 控制器
- 開發規范
- 配置
- 配置格式
- 配置加載
- 讀取配置
- 動態配置
- 擴展配置
- 批量配置
- 架構
- 模塊化設計
- URL模式
- 多層MVC
- CBD模式
- 命名空間
- 自動加載
- 應用模式
- 項目編譯
- 系統流程
- 路由
- 路由定義
- 規則路由
- 正則路由
- 靜態路由
- 閉包支持
- 實例說明
- 控制器
- 控制器定義
- 前置和后置操作
- Action參數綁定
- 偽靜態
- URL大小寫
- URL生成
- AJAX返回
- 跳轉和重定向
- 輸入變量
- 請求類型
- 空操作
- 空控制器
- 插件控制器
- 操作綁定到類
- 模型
- 模型定義
- 模型實例化
- 字段定義
- 連接數據庫
- 切換數據庫
- 分布式數據庫支持
- 連貫操作
- WHERE
- TABLE
- ALIAS
- DATA
- FIELD
- ORDER
- LIMIT
- PAGE
- GROUP
- HAVING
- JOIN
- UNION
- DISTINCT
- LOCK
- CACHE
- COMMENT
- RELATION
- USING
- fetchSql
- TOKEN
- STRICT
- INDEX
- 命名范圍
- CURD操作
- 數據創建
- 數據寫入
- 數據讀取
- 數據更新
- 數據刪除
- ActiveRecord
- 字段映射
- 查詢語言
- 查詢方式
- 表達式查詢
- 快捷查詢
- 區間查詢
- 組合查詢
- 統計查詢
- SQL查詢
- 動態查詢
- 子查詢
- 自動驗證
- 自動完成
- 參數綁定
- 虛擬模型
- 模型分層
- 視圖模型
- 關聯模型
- 高級模型
- Mongo模型
- 視圖
- 模板定義
- 模板主題
- 模板賦值
- 模板渲染
- 獲取模板地址
- 獲取內容
- 模板引擎
- 模板
- 變量輸出
- 系統變量
- 使用函數
- 默認值輸出
- 使用運算符
- 標簽庫
- 模板繼承
- 修改定界符
- 三元運算
- 包含文件
- 內置標簽
- Volist標簽
- Foreach標簽
- For標簽
- Switch標簽
- 比較標簽
- 范圍判斷標簽
- IF標簽
- Present標簽
- Empty標簽
- Defined標簽
- Assign標簽
- Define標簽
- 標簽嵌套
- import標簽
- 使用PHP代碼
- 原樣輸出
- 模板注釋
- 模板布局
- 模板替換
- 調試
- 調試模式
- 異常處理
- 日志記錄
- 頁面Trace
- Trace方法
- 變量調試
- 性能調試
- 錯誤調試
- 模型調試
- 緩存
- 數據緩存
- 快速緩存
- 查詢緩存
- 靜態緩存
- 安全
- 輸入過濾
- 表單合法性檢測
- 表單令牌
- 防止SQL注入
- 目錄安全文件
- 保護模板文件
- 上傳安全
- 防止XSS攻擊
- 其他安全建議
- 擴展
- 類庫擴展
- 驅動擴展
- 緩存驅動
- 數據庫驅動
- 日志驅動
- Session驅動
- 存儲驅動
- 模板引擎驅動
- 標簽庫驅動
- 行為擴展
- 標簽擴展
- Widget擴展
- 應用模式
- 部署
- PATH_INFO支持
- URL重寫
- 模塊部署
- 域名部署
- 入口綁定
- 替換入口
- 專題
- SESSION支持
- Cookie支持
- 多語言支持
- 數據分頁
- 文件上傳
- 驗證碼
- 圖像處理
- RESTFul
- RPC
- SAE
- IP獲取和定位
- 附錄
- 常量參考
- 配置參考
- 升級指導
- 鳴謝