1. 程式人生 > >TP3.2.3檔案上傳

TP3.2.3檔案上傳

上傳表單

在ThinkPHP中使用上傳功能無需進行特別處理。例如,下面是一個帶有附件上傳的表單提交:

  1. <formaction="__URL__/upload"enctype="multipart/form-data"method="post">
  2. <inputtype="text"name="name"/>
  3. <inputtype="file"name="photo"/>
  4. <inputtype="submit"value="提交">
  5. </form>

注意,要使用上傳功能 你的表單需要設定 enctype="multipart/form-data"

多檔案上傳支援

如果需要使用多個檔案上傳,只需要修改表單,把

  1. <inputtype='file'name='photo'>

改為

  1. <inputtype='file'name='photo1'>
  2. <inputtype='file'name='photo2'>
  3. <inputtype='file'name='photo3'>

或者

  1. <inputtype='file'name='photo[]'>
  2. <inputtype='file'name='photo[]'>
  3. <inputtype='file'name='photo[]'>

兩種方式的多附件上傳系統的檔案上傳類都可以自動識別。

上傳操作

ThinkPHP檔案上傳操作使用Think\Upload類,假設前面的表單提交到當前控制器的upload方法,我們來看下upload方法的實現程式碼:

  1. publicfunction upload(){
  2. $upload =new \Think\Upload();// 例項化上傳類
  3. $upload->maxSize =3145728;// 設定附件上傳大小
  4. $upload->exts = array('jpg','gif','png','jpeg');// 設定附件上傳型別
  5. $upload->rootPath ='./Uploads/'
    ;// 設定附件上傳根目錄
  6. $upload->savePath ='';// 設定附件上傳(子)目錄
  7. // 上傳檔案
  8. $info = $upload->upload();
  9. if(!$info){// 上傳錯誤提示錯誤資訊
  10. $this->error($upload->getError());
  11. }else{// 上傳成功
  12. $this->success('上傳成功!');
  13. }
  14. }

上傳類對圖片檔案的上傳安全做了支援,如果企圖上傳非法的影象檔案,系統會提示 非法影象檔案。 為了更好的使用上傳功能,建議你的伺服器開啟finfo模組支援

上傳引數

在上傳操作之前,我們可以對上傳的屬性進行一些設定,Upload類支援的屬性設定包括:

屬性 描述
maxSize 檔案上傳的最大檔案大小(以位元組為單位),0為不限大小
rootPath 檔案上傳儲存的根路徑
savePath 檔案上傳的儲存路徑(相對於根路徑)
saveName 上傳檔案的儲存規則,支援陣列和字串方式定義
saveExt 上傳檔案的儲存字尾,不設定的話使用原檔案字尾
replace 存在同名檔案是否是覆蓋,預設為false
exts 允許上傳的檔案字尾(留空為不限制),使用陣列或者逗號分隔的字串設定,預設為空
mimes 允許上傳的檔案型別(留空為不限制),使用陣列或者逗號分隔的字串設定,預設為空
autoSub 自動使用子目錄儲存上傳檔案 預設為true
subName 子目錄建立方式,採用陣列或者字串方式定義
hash 是否生成檔案的hash編碼 預設為true
callback 檢測檔案是否存在回撥,如果存在返回檔案資訊陣列

上面的屬性可以通過兩種方式傳入:

例項化傳入

我們可以在例項化的時候直接傳入引數陣列,例如:

  1. $config = array(
  2. 'maxSize'=>3145728,
  3. 'rootPath'=>'./Uploads/',
  4. 'savePath'=>'',
  5. 'saveName'=> array('uniqid',''),
  6. 'exts'=> array('jpg','gif','png','jpeg'),
  7. 'autoSub'=>true,
  8. 'subName'=> array('date','Ymd'),
  9. );
  10. $upload =new \Think\Upload($config);// 例項化上傳類

關於saveName和subName的使用後面我們會有詳細的描述。

動態賦值

支援在例項化後動態賦值上傳引數,例如:

  1. $upload =new \Think\Upload();// 例項化上傳類
  2. $upload->maxSize =3145728;
  3. $upload->rootPath ='./Uploads/';
  4. $upload->savePath ='';
  5. $upload->saveName = array('uniqid','');
  6. $upload->exts = array('jpg','gif','png','jpeg');
  7. $upload->autoSub =true;
  8. $upload->subName = array('date','Ymd');

上面的設定和例項化傳入的效果是一致的。

上傳檔案資訊

設定好上傳的引數後,就可以呼叫Think\Upload類的upload方法進行附件上傳,如果失敗,返回false,並且用getError方法獲取錯誤提示資訊;如果上傳成功,就返回成功上傳的檔案資訊陣列。

  1. $upload =new \Think\Upload();// 例項化上傳類
  2. $upload->maxSize =3145728;// 設定附件上傳大小
  3. $upload->exts = array('jpg','gif','png','jpeg');// 設定附件上傳型別
  4. $upload->rootPath ='./Uploads/';// 設定附件上傳根目錄
  5. $upload->savePath ='';// 設定附件上傳(子)目錄
  6. // 上傳檔案
  7. $info = $upload->upload();
  8. if(!$info){// 上傳錯誤提示錯誤資訊
  9. $this->error($upload->getError());
  10. }else{// 上傳成功 獲取上傳檔案資訊
  11. foreach($info as $file){
  12. echo $file['savepath'].$file['savename'];
  13. }
  14. }

每個檔案資訊又是一個記錄了下面資訊的陣列,包括:

屬性 描述
key 附件上傳的表單名稱
savepath 上傳檔案的儲存路徑
name 上傳檔案的原始名稱
savename 上傳檔案的儲存名稱
size 上傳檔案的大小
type 上傳檔案的MIME型別
ext 上傳檔案的字尾型別
md5 上傳檔案的md5雜湊驗證字串 僅當hash設定開啟後有效
sha1 上傳檔案的sha1雜湊驗證字串 僅當hash設定開啟後有效

檔案上傳成功後,就可以使用這些檔案資訊來進行其他的資料操作,例如儲存到當前資料表或者單獨的附件資料表。

例如,下面表示把上傳資訊儲存到資料表的欄位:

  1. $model = M('Photo');
  2. // 取得成功上傳的檔案資訊
  3. $info = $upload->upload();
  4. // 儲存當前資料物件
  5. $data['photo']= $info[0]['savename'];
  6. $data['create_time']= NOW_TIME;
  7. $model->add($data);

單檔案上傳

upload方法支援多檔案上傳,有時候,我們只需要上傳一個檔案,就可以使用Upload類提供的uploadOne方法上傳單個檔案,例如:

  1. publicfunction upload(){
  2. $upload =new \Think\Upload();// 例項化上傳類
  3. $upload->maxSize =3145728;// 設定附件上傳大小
  4. $upload->exts = array('jpg','gif','png','jpeg');// 設定附件上傳型別
  5. $upload->rootPath ='./Uploads/';// 設定附件上傳根目錄
  6. // 上傳單個檔案
  7. $info = $upload->uploadOne($_FILES['photo1']);
  8. if(!$info){// 上傳錯誤提示錯誤資訊
  9. $this->error($upload->getError());
  10. }else{// 上傳成功 獲取上傳檔案資訊
  11. echo $info['savepath'].$info['savename'];
  12. }
  13. }

uploadOne方法上傳成功後返回的檔案資訊和upload方法的區別是隻有單個檔案資訊的一維陣列。

上傳檔案的命名規則

上傳檔案的命名規則(saveName)用於確保檔案不會產生衝突或者覆蓋的情況。命名規則的定義可以根據你的業務邏輯來調整,不是固定的。例如,如果你採用時間戳的方式來定義命名規範,那麼在同時上傳多個檔案的時候可能產生衝突(因為同一秒內可以上傳多個檔案),因此你需要根據你的業務需求來設定合適的上傳命名規則。這裡順便來說下saveName引數的具體用法。

一、採用函式方式

如果傳入的字串是一個函式名,那麼表示採用函式動態生成上傳檔名(不包括檔案字尾),例如:

  1. // 採用時間戳命名
  2. $upload->saveName ='time';
  3. // 採用GUID序列命名
  4. $upload->saveName ='com_create_guid';

也可以採用使用者自定義函式

  1. // 採用自定義函式命名
  2. $upload->saveName ='myfun';

預設的命名規則設定是採用uniqid函式生成一個唯一的字串序列。

saveName的值支援陣列和字串兩種方式,如果是隻有一個引數或者沒有引數的函式,直接使用字串設定即可,如果需要傳入額外的引數,可以使用陣列方式,例如:

  1. // 採用date函式生成命名規則 傳入Y-m-d引數
  2. $upload->saveName = array('date','Y-m-d');
  3. // 如果有多個引數需要傳入的話 可以使用陣列
  4. $upload->saveName = array('myFun',array('__FILE__','val1','val2'));

如果需要使用上傳的原始檔名,可以採用__FILE__傳入,所以上面的定義規則,最終的結果是 myFun('上傳檔名','val1','val2')執行的結果。

二、直接設定上傳檔名

如果傳入的引數不是一個函式名,那麼就會直接當做是上傳檔名,例如:

  1. $upload->saveName = time().'_'.mt_rand();

表示上傳的檔案命名採用時間戳加一個隨機數的組合字串方式。

當然,如果覺得有必要,你還可以固定設定一個上傳檔案的命名規則,用於固定儲存某個上傳檔案。

  1. $upload->saveName ='ThinkPHP';

三、保持上傳檔名不變

如果你想保持上傳的檔名不變,那麼只需要設定命名規範為空即可,例如:

  1. $upload->saveName ='';

一般來說不建議保持不變,因為會導致相同的檔名上傳後被覆蓋的情況。

子目錄儲存

saveName只是用於設定檔案的儲存規則,不涉及到目錄,如果希望對上傳的檔案分子目錄儲存,可以設定autoSubsubName引數來完成,例如:

  1. // 開啟子目錄儲存 並以日期(格式為Ymd)為子目錄
  2. $upload->autoSub =true;
  3. $upload->subName = array('date','Ymd');

可以使用自定義函式來儲存,例如:

  1. // 開啟子目錄儲存 並呼叫自定義函式get_user_id生成子目錄
  2. $upload->autoSub =true;
  3. $upload->subName ='get_user_id';

和saveName引數一樣,subName的定義可以採用陣列和字串的方式。

注意:如果get_user_id函式未定義的話,會直接以get_user_id字串作為子目錄的名稱儲存。

子目錄儲存和檔案命名規則可以結合使用。

上傳驅動

上傳類可以支援不同的環境,通過相應的上傳驅動來解決,預設情況下使用本地(Local)上傳驅動,當然,你還可以設定當前預設的上傳驅動型別,例如:

  1. 'FILE_UPLOAD_TYPE'=>'Ftp',
  2. 'UPLOAD_TYPE_CONFIG'=> array(
  3. 'host'=>'192.168.1.200',//伺服器
  4. 'port'=>21,//埠
  5. 'timeout'=>90,//超時時間
  6. 'username'=>'ftp_user',//使用者名稱
  7. 'password'=>'ftp_pwd',//密碼 ),

表示當前使用Ftp作為上傳類的驅動,上傳的檔案會通過FTP傳到指定的遠端伺服器。

也可以在例項化上傳類的時候指定,例如:

  1. $config = array(
  2. 'maxSize'=3145728,
  3. 'rootPath'='./Uploads/',
  4. 'savePath'='',
  5. 'saveName'= array('uniqid',''),
  6. 'exts'= array('jpg','gif','png','jpeg'),
  7. 'autoSub'=true,
  8. 'subName'= array('date','Ymd'),
  9. );
  10. $ftpConfig = array(
  11. 'host'=>'192.168.1.200',//伺服器
  12. 'port'=>21,//埠
  13. 'timeout'=>90,//超時時間
  14. 'username'=>'ftp_user',//使用者名稱
  15. 'password'=>'ftp_pwd',//密碼 );
  16. $upload =new \Think\Upload($config,'Ftp',$ftpConfig);// 例項化上傳類