PHP 文件上傳操作類

[TOC]

前言

今天在公司無(wú)事,就搞了下文件上傳的東東箕宙,方便自己的學(xué)習(xí)嚎朽,和今后的使用,目前只支持單文件上傳柬帕。下面是代碼部分哟忍,也可以訪問(wèn)我的 GiteeGithub,不想看代碼的童鞋可以直接[下載]陷寝。锅很。。(算了凤跑,討厭百度云爆安,如果有需要的話留言)代碼使用,使用方法請(qǐng)點(diǎn)擊

代碼

<?php

namespace E;

class FileUpload
{
    /**
     * @var $name 上傳文件標(biāo)記名
     */
    protected $name = 'file';

    /**
     * @var $ext 所允許的擴(kuò)展名
     */
    protected $exts  = [];

    /**
     * @var $file 上傳的文件資源
     */
    protected $file = null;

    /**
     * @var $upload_success 是否上傳成功標(biāo)志
     */
    protected $upload_success = false;

    /**
     * @var $max_size 上傳文件所允許的大小仔引,單位為 M
     */
    protected $max_size = 2;

    /**
     * @var $error_code 錯(cuò)誤碼
     */
    protected $error_code = 0;

    /**
     * @var $error_msg 錯(cuò)誤信息
     */
    protected $error_msg = '';

    /**
     * @var $file_ext 文件擴(kuò)展名
     */
    protected $file_ext = '';

    /**
     * @var $type 文件類型扔仓,默認(rèn)為任意類型
     */
    protected $type = 'file';

    protected const ERR_OK         = 0;
    protected const ERR_FILE_SIZE  = 1;
    protected const ERR_FORM_SIZE  = 2;
    protected const ERR_PARTIAL    = 3;
    protected const ERR_NO_FILE    = 4;
    protected const ERR_FILE_EXIST = 5;
    protected const ERR_NO_TMP_DIR = 6;
    protected const ERR_CANT_WRITE = 7;
    protected const ERR_FILE_TYPE  = 8;

    /**
     * 配置上傳信息
     *
     * @param array $arr
     * @return E\FileUpload
     */
    public function config($arr)
    {
        foreach ($arr as $key => $val) {
            if (property_exists($this, $key)) {
                $this->$key = $val;
            }
        }
        return $this;
    }

    /**
     * 進(jìn)行文件上傳操作
     *
     * @return E\FileUpload
     */
    public function upload()
    {
        $this->file     = $this->getFile();
        $this->file_ext = strrchr($this->file['name'], '.');

        $this->upload_success = !($this->uploadError() || $this->overMaxSize() || $this->notAllowType());

        return $this;
    }

    /**
     * 判斷文件是否上傳成功
     * 
     * @return boolean
     */
    public function uploadSuccess()
    {
        return $this->upload_success;
    }

    /**
     * 保存已上傳的文件
     *
     * @param string $path
     * @param string $file_name
     *
     * @return boolean
     */
    public function save($path, $file_name = '')
    {
        if (!$this->uploadSuccess()) {
            return false;
        }

        // 判斷文件夾是否存在褐奥,如果不存在,新建一個(gè)文件夾
        if (!is_dir($path)) {
            mkdir($path);
        }

        // 獲取文件名翘簇,不包含后綴
        $file_name = $file_name ?: 'e_' . time() . mt_rand(10000, 99999);

        $file = rtrim($path, '/') . '/' . $file_name . $this->file_ext;

        // 判斷文件是否存在
        if (file_exists($file)) {
            $this->error_code = self::ERR_FILE_EXIST;
            return false;
        }

        if (move_uploaded_file($this->file['tmp_name'], $file)) {
            return true;
        }

        // 文件未上傳成功撬码,出現(xiàn)未知錯(cuò)誤
        $this->error_code = -1;
        return false;
    }

    /**
     * 返回錯(cuò)誤碼
     * 
     * @return integer
     */
    public function errorCode()
    {
        return $this->error_code;
    }

    /**
     * 返回錯(cuò)誤信息
     *
     * @return string
     */
    public function errorMsg()
    {
        !$this->error_msg && $this->setErrorMsgByCode($this->error_code);

        return $this->error_msg;
    }

    /**
     * 獲取上傳文件
     * 
     * @return mixed
     */
    protected function getFile()
    {
        return $_FILES[$this->name];
    }

    /**
     * 判斷是否上傳錯(cuò)誤
     * 
     * @return boolean
     */
    protected function uploadError()
    {
        $this->error_code = $this->file['error'];

        return (bool)$this->file['error'];
    }

    /**
     * 根據(jù)錯(cuò)誤代碼設(shè)置錯(cuò)誤信息
     *
     * @param  int $code
     */
    protected function setErrorMsgByCode($code)
    {
        $msg_arr = [
            '',
            '上傳文件最大為 ' . $this->getMaxSize() . 'M',
            '上傳文件過(guò)大',
            '文件只有部分被上傳',
            '沒(méi)有文件被上傳',
            '文件已存在',
            '文件丟失',
            '文件寫(xiě)入失敗',
            '只能上傳' . implode(',', $this->exts) . '類型的文件'
        ];

        $this->error_msg = $msg_arr[$code] ?? '未知錯(cuò)誤';
    }

    /**
     * 獲取上傳文件所限制的最大大小
     * 
     * @return int
     */
    protected function getMaxSize()
    {
        return min($this->max_size, (int)ini_get('upload_max_filesize'));
    }

    /**
     * 判斷文件是否超出限制大小
     *
     * @return boolean
     */
    protected function overMaxSize()
    {
        if ($this->file['size'] > $this->getMaxSize() * 1024 * 1024 * 8) {
            $this->error_code = self::ERR_FILE_SIZE;
            return true;
        }
        return false;
    }

    /**
     * 通過(guò)類型獲取后綴名數(shù)組
     *
     * @return array
     */
    protected function getExtsByType()
    {
        $exts_arr = [
            'image' => ['jpg', 'jpeg', 'png', 'gif'],
            'file'  => [],
            'zip'   => ['zip', 'rar', '7z']
        ];

        return $exts_arr[$this->type] ?? [];
    }

    /**
     * 判斷是否是允許的類型
     * 
     * @return boolean
     */
    protected function notAllowType()
    {
        $this->exts = $this->exts ?: $this->getExtsByType();

        if (!$this->exts) return false;

        if (preg_match('/^\.' . implode('|', $this->exts) . '$/i', $this->file_ext)) {
            return false;
        }

        $this->error_code = self::ERR_FILE_TYPE;
        return true;
    }
}

使用方法

  1. 引入文件
include 'FileUpload.class.php';
  1. 實(shí)例化類
$uploader = new E\FileUpload();
  1. 配置
$uploader->config([
    'name'      => 'file',
    'exts'      => ['jpg'],
    'type'      => 'image',
    'max_size'  => 2,
]);

配置項(xiàng)的說(shuō)明:

配置項(xiàng) 說(shuō)明
name 是 HTML 中 input 的 name,例如: <input type="file" name="file">版保,默認(rèn)是 file
exts 所允許上傳的文件擴(kuò)展名呜笑,類型為數(shù)組,默認(rèn)是任何類型的文件
type 上傳文件類型彻犁,可以通過(guò)設(shè)置 type 屬性叫胁,設(shè)置允許上傳類型,默認(rèn)為 file袖裕,
目前可選類型有:file 全部文件類型曹抬,image 圖片類型, zip 壓縮包急鳄,
注意:exts優(yōu)先級(jí)高于 type谤民,
即如果設(shè)置了 type 為 file,exts 為 ['jpg'] 時(shí)疾宏,也還是只能上傳 jpg 類型的文件的
max_size 所允許上傳的大小张足,單位為 M,默認(rèn)為 2M
  1. 上傳
$uploader->upload();
  1. 保存
$uploader->save('./uploads/', 'test')

save 方法的返回值是一個(gè)布爾值坎藐,上傳成功返回 true为牍,失敗返回 false,可以根據(jù)返回的狀態(tài)進(jìn)行相應(yīng)的操作岩馍,如果失敗碉咆,可以使用 errorCode() 方法獲取錯(cuò)誤代碼,使用 errorMsg() 方法獲取錯(cuò)誤信息蛀恩。

save 方法的第一個(gè)參數(shù)為必填參數(shù)疫铜,是要保存的路徑,第二個(gè)參數(shù)是文件名双谆,可選壳咕,如果不填,則會(huì)自動(dòng)生成顽馋,生成規(guī)則: e_ 連接上當(dāng)前時(shí)間的時(shí)間戳再連接5位隨機(jī)數(shù)

也可以使用鏈?zhǔn)讲僮鳎?/p>

$uploader->upload()->save('./uploads/', 'test');

錯(cuò)誤碼說(shuō)明

錯(cuò)誤碼 說(shuō)明
0 無(wú)錯(cuò)誤
1 上傳文件超出限制大小
2 上傳文件超出 form 表單所設(shè)置的 MAX_FILE_SIZE谓厘,也是文件過(guò)大
3 文件只有部分被上傳
4 沒(méi)有文件被上傳
5 存在同名文件
6 文件丟失
7 文件寫(xiě)入失敗
8 上傳的文件類型不被允許
-1 未知錯(cuò)誤
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市寸谜,隨后出現(xiàn)的幾起案子竟稳,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件住练,死亡現(xiàn)場(chǎng)離奇詭異地啰,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)讲逛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門亏吝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人盏混,你說(shuō)我怎么就攤上這事蔚鸥。” “怎么了许赃?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵止喷,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我混聊,道長(zhǎng)弹谁,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任句喜,我火速辦了婚禮预愤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘咳胃。我一直安慰自己植康,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布展懈。 她就那樣靜靜地躺著销睁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪存崖。 梳的紋絲不亂的頭發(fā)上冻记,一...
    開(kāi)封第一講書(shū)人閱讀 52,682評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音来惧,去河邊找鬼冗栗。 笑死,一個(gè)胖子當(dāng)著我的面吹牛违寞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播偶房,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼趁曼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了棕洋?” 一聲冷哼從身側(cè)響起挡闰,我...
    開(kāi)封第一講書(shū)人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后摄悯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體赞季,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年奢驯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了申钩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瘪阁,死狀恐怖撒遣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情管跺,我是刑警寧澤义黎,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站豁跑,受9級(jí)特大地震影響廉涕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜艇拍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一狐蜕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧淑倾,春花似錦馏鹤、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至碍讨,卻和暖如春治力,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背勃黍。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工宵统, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人覆获。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓马澈,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親弄息。 傳聞我的和親對(duì)象是個(gè)殘疾皇子痊班,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361