上傳是一個網站里必不可少的功能,我們借助TP的上傳類,可以方便的支持上傳回調和云空間上傳。
## 編輯器上傳
為了簡化問題,我們只允許編輯器里上傳圖片。
然后編輯器配置里指定了上傳的方法

然后雖然對應方法只有幾行代碼:
~~~
public function ueditor(){
$data = new \Org\Util\Ueditor();
die($data->output());
}
~~~
但是還要設置對應的json配置

如對應的保存目錄、后綴等規則。
這里注意,編輯器上傳的類里把不同文件類型的劃分了不同的action。

而我的圖片上傳插件plupload由于返回和系統上傳的不一樣,我干脆就利用了編輯器上傳,通過穿參上傳圖片。

~~~
public function plupload(){
$data = new \Org\Util\Ueditor();
$json = $data->output();
$result = json_decode($json, 1);
if('SUCCESS' == $result['state']){
$output = array(
'ok'=>1,
'path'=>$result['url'],
);
}else{
$output = array(
'ok'=>0,
'code'=>$result['state'],
);
}
die(json_encode($output));
}
~~~
## 系統上傳
系統上傳主要把上傳的對象定位圖片和文件兩種類型。
然后參照OneThink,給不同類型設置不同的驅動和上傳配置。兩種類型的文件分別存在File表和Picture表里。
上傳配置:
~~~
'PICTURE_UPLOAD_DRIVER'=>'Local',
'FILE_UPLOAD_DRIVER'=>'Local',
/* 文件上傳相關配置 */
'FILE_UPLOAD' => array(
'mimes' => '', //允許上傳的文件MiMe類型
'maxSize' => 1024*1024*1024, //上傳的文件大小限制 (0-不做限制)
'exts' => 'jpg,gif,png,jpeg,zip,rar,tar,gz,7z,doc,docx,txt,xml,mp3,mp4', //允許上傳的文件后綴
'autoSub' => true, //自動子目錄保存文件
'subName' => array('date', 'Y-m-d'), //子目錄創建方式,[0]-函數名,[1]-參數,多個參數使用數組
'rootPath' => './Uploads/file/', //保存根路徑
'savePath' => '', //保存路徑
'saveName' => array('uniqid', ''), //上傳文件命名規則,[0]-函數名,[1]-參數,多個參數使用數組
'saveExt' => '', //文件保存后綴,空則使用原后綴
'replace' => false, //存在同名是否覆蓋
'hash' => true, //是否生成hash編碼
'callback' => false, //檢測文件是否存在回調函數,如果存在返回文件信息數組
), //下載模型上傳配置(文件上傳類配置)
/* 圖片上傳相關配置 */
'PICTURE_UPLOAD' => array(
'mimes' => '', //允許上傳的文件MiMe類型
'maxSize' => 2*1024*1024, //上傳的文件大小限制 (0-不做限制)
'exts' => 'jpg,gif,png,jpeg,tmp', //允許上傳的文件后綴
'autoSub' => true, //自動子目錄保存文件
'subName' => array('date', 'Y-m-d'), //子目錄創建方式,[0]-函數名,[1]-參數,多個參數使用數組
'rootPath' => './Uploads/picture/', //保存根路徑
'savePath' => '', //保存路徑
'saveName' => array('uniqid', ''), //上傳文件命名規則,[0]-函數名,[1]-參數,多個參數使用數組
'saveExt' => '', //文件保存后綴,空則使用原后綴
'replace' => false, //存在同名是否覆蓋
'hash' => true, //是否生成hash編碼
'callback' => false, //檢測文件是否存在回調函數,如果存在返回文件信息數組
), //圖片上傳相關配置(文件上傳類配置)
~~~
上傳主要代碼:
~~~
public function ajaxUpload($model= 'File',$field='file') {
$params = array('model'=>$model, 'field'=>$field);
slog($params);
$result = $this->upload($params);
if ($result['status']) {
$result['info'] = '上傳成功';
} else {
$result['status'] = 0;
$result['info'] = '上傳失敗'.$result['info'];
}
$this->ajaxReturn($result);
}
protected function upload($params) {
slog($params);
/* 返回標準數據 */
$return = array('status' => 1, 'info' => '上傳成功', 'data' => '');
$model = $params['model'] == 'Picture'? 'Picture' : 'File';
/* 調用文件上傳組件上傳文件 */
$table = D($model);
$driver = C("{$model}_UPLOAD_DRIVER");
d_f('upload', $driver);
$upload_config = C("{$model}_UPLOAD");
d_f('upload', $upload_config);
if(isset($params['rootPath']))
$upload_config['rootPath'] = $params['rootPath'];
$info = $table->upload($_FILES, $upload_config, $driver, C("UPLOAD_{$driver}_CONFIG"));
d_f('upload', $info);
/* 記錄圖片信息 */
if ($info) {
$return['status'] = 1;
$return = array_merge($info[$params['field']], $return);
if (method_exists($this, 'after_upload')) {
$this->after_upload(CONTROLLER_NAME, $info, $result);
}
} else {
$return['status'] = 0;
$return['info'] = $table->getError();
}
d_f('upload', $return);
return $return;
}
~~~
先是封裝了一個上傳方法,并且支持回調`after_upload`。
然后,封裝了一個系統用的ajaxUpload 方法用于返回json響應。
上傳方法中調用對應模型的upload方法,比如FileModel的upload
~~~
/**
* 文件上傳
* @param array $files 要上傳的文件列表(通常是$_FILES數組)
* @param array $setting 文件上傳配置
* @param string $driver 上傳驅動名稱
* @param array $config 上傳驅動配置
* @return array 文件上傳成功后的信息
*/
public function upload($files, $setting, $driver = 'Local', $config = null){
/* 上傳文件 */
$setting['callback'] = array($this, 'isFile');
$setting['removeTrash'] = array($this, 'removeTrash');
$Upload = new Upload($setting, $driver, $config);
$info = $Upload->upload($files);
/* 設置文件保存位置 */
$this->_auto[] = array('location', 'ftp' === strtolower($driver) ? 1 : 0, self::MODEL_INSERT);
if($info){ //文件上傳成功,記錄文件信息
foreach ($info as $key => &$value) {
/* 已經存在文件記錄 */
if(isset($value['id']) && is_numeric($value['id'])){
$value['path'] = substr($setting['rootPath'], 1).$value['savepath'].$value['savename']; //在模板里的url路徑
continue;
}
/* 記錄文件信息 */
$value['path'] = substr($setting['rootPath'], 1).$value['savepath'].$value['savename']; //在模板里的url路徑
if($this->create($value) && ($id = $this->add())){
$value['id'] = $id;
} else {
//TODO: 文件上傳成功,但是記錄文件信息失敗,需記錄日志
unset($info[$key]);
}
}
return $info; //文件上傳成功
} else {
$this->error = $Upload->getError();
return false;
}
}
~~~
方法進行了文件重復的上傳判斷和上傳完畢后入庫的操作。
為了方便在沒有slog的時候調試。我還寫了一個`d_f`函數 替代f函數寫文件記錄調試信息。
~~~
/**
* 快速文件數據讀取和保存 針對簡單類型數據 字符串、數組
* @param string $name 緩存名稱
* @param mixed $value 緩存值
* @param string $path 緩存路徑
* @return mixed
*/
function d_f($name, $value, $path = DATA_PATH) {
static $_cache = array();
$filename = $path . $name . '.php';
if ('' !== $value) {
if (is_null($value)) {
// 刪除緩存
// return false !== strpos($name,'*')?array_map("unlink", glob($filename)):unlink($filename);
} else {
// 緩存數據
$dir = dirname($filename);
// 目錄不存在則創建
if (!is_dir($dir))
mkdir($dir, 0755, true);
$_cache[$name] = $value;
$content = strip_whitespace("<?php\treturn " . var_export($value, true) . ";?>") . PHP_EOL;
return file_put_contents($filename, $content, FILE_APPEND);
}
}
if (isset($_cache[$name]))
return $_cache[$name];
// 獲取緩存數據
if (is_file($filename)) {
$value = include $filename;
$_cache[$name] = $value;
} else {
$value = false;
}
return $value;
}
~~~
他比f函數直接寫日志的優勢是,追加記錄文件。
像這樣

默認記錄在runtime 下data目錄里。
- 序
- 前言
- 內容簡介
- 目錄
- 基礎知識
- 起步
- 控制器
- 模型
- 模板
- 命名空間
- 進階知識
- 路由
- 配置
- 緩存
- 權限
- 擴展
- 國際化
- 安全
- 單元測試
- 拿來主義
- 調試方法
- 調試的步驟
- 調試工具
- 顯示trace信息
- 開啟調試和關閉調試的區別
- netbeans+xdebug
- Socketlog
- PHP常見錯誤
- 小黃鴨調試法,每個程序員都要知道的
- 應用場景
- 第三方登錄
- 圖片處理
- 博客
- SAE
- REST實踐
- Cli
- ajax分頁
- barcode條形碼
- excel
- 發郵件
- 漢字轉全拼和首字母,支持帶聲調
- 中文分詞
- 瀏覽器useragent解析
- freelog項目實戰
- 需求分析
- 數據庫設計
- 編碼實踐
- 前端實現
- rest接口
- 文章發布
- 文件上傳
- 視頻播放
- 音樂播放
- 圖片幻燈片展示
- 注冊和登錄
- 個人資料更新
- 第三方登錄的使用
- 后臺
- 微信的開發
- 首頁及個人主頁
- 列表
- 歸檔
- 搜索
- 分頁
- 總結經驗
- 自我提升
- 進行小項目的鍛煉
- 對現有輪子的重構和移植
- 寫技術博客
- 制作視頻教程
- 學習PHP的知識和新特性
- 和同行直接溝通、交流
- 學好英語,走向國際
- 如何參與
- 瀏覽官網和極思維還有看云
- 回答ThinkPHP新手的問題
- 嘗試發現ThinkPHP的bug,告訴官方人員或者push request
- 開發能提高效率的ThinkPHP工具
- 嘗試翻譯官方文檔
- 幫新手入門
- 創造基于ThinkPHP的產品,進行連帶推廣
- 展望未來
- OneThink
- ThinkPHP4
- 附錄