首先用php的socket函數庫建立一個臨時的http服務器,在某一端口監聽,然后把 ip地址和端口號通知客戶端,客戶端把上傳表單提交(臨時服務器),臨時服務器接受客戶端請求,并讀取post數據,分析并獲取客戶端上傳的文件信息,把文件保存在服務器上,然后關閉臨時服務器,釋放資源,上傳完成,有點繞,不過思路還是簡單的,代碼如下:
- <?php
- class upload {
- public $up_ext=array(), $up_max=5210, $up_dir;
- private $up_name, $up_rename=true, $up_num=0, $up_files=array(), $up_ret=array();
- function __construct($name, $ext=array(), $rename=true) {
- if (!emptyempty($name)) {
- $this->up_name = $name;
- !emptyempty($ext) && $this->up_ext = $ext;
- $this->up_rename = $rename;
- $this->up_dir = website_dirroot.
- $globals['cfg_upload_path'];
- $this->initupload();
- } else {
- exit('upload文件域名稱為空,初始化失?。?#39;);
- }
- }
- private function initupload() {
- if (is_array($_files[$this->up_name])) {
- $up_arr = count($_files[$this->up_name]);
- $up_all = count($_files[$this->up_name], 1);
- $up_cnt = ($up_all - $up_arr) / $up_arr;
- for ($i = 0; $i < $up_cnt; $i ++) {
- if ($_files[$this->up_name]['error'][$i] != 4) {
- $this->up_files[] = array(
- 'tmp_name' => $_files[$this->up_name]['tmp_name'][$i],
- 'name' => $_files[$this->up_name]['name'][$i],
- 'type' => $_files[$this->up_name]['type'][$i],
- 'size' => $_files[$this->up_name]['size'][$i],
- 'error' => $_files[$this->up_name]['error'][$i]
- );
- }
- }
- $this->up_num = count($this->up_files);
- } else {
- if (isset($_files[$this->up_name])) {
- $this->up_files = array(
- 'tmp_name' => $_files[$this->up_name]['tmp_name'],
- 'name' => $_files[$this->up_name]['name'],
- 'type' => $_files[$this->up_name]['type'],
- 'size' => $_files[$this->up_name]['size'],
- 'error' => $_files[$this->up_name]['error']
- );
- $this->up_num = 1;
- } else {
- exit('沒找找到需要upload的文件!');
- }
- }
- $this->chkupload();
- }
- private function chkupload() {
- if (emptyempty($this->up_ext)) {
- $up_mime = array('image/wbmp', 'image/bmp', 'image/gif', 'image/pjpeg', 'image/x-png');
- foreach ($this->up_files as $up_file) {
- $up_allw = false;
- foreach ($up_mime as $mime) {
- if ($up_file['type'] == $mime) {
- $up_allw = true; break;
- }
- }
- !$up_allw && exit('不允許上傳'.$up_file['type'].'格式的文件!');
- if ($up_file['size'] / 1024 > $this->up_max) {
- exit('不允許上傳大于 '.$this->up_max.'k 的文件!');
- }
- }
- } else {
- foreach ($this->up_files as $up_file) {
- $up_ext = end(explode('.', $up_file['name']));
- $up_allw = false;
- foreach ($this->up_ext as $ext) {
- if ($up_ext == $ext) {
- $up_allw = true; break;
- }
- }
- !$up_allw && exit('不允許上傳.'.$up_ext.'格式的文件!');
- if ($up_file['size'] / 1024 > $this->up_max) {
- exit('不允許上傳大于 '.$this->up_max.'k 的文件!');
- }
- }
- }
- $this->uploading();
- }
- private function uploading() {
- if (io::dircreate($this->up_dir)) {
- if (chmod($this->up_dir, 0777)) {
- if (!emptyempty($this->up_files)) {
- foreach ($this->up_files as $up_file) {
- if (is_uploaded_file($up_file['tmp_name'])) {
- $file_name = $up_file['name'];
- if ($this->up_rename) {
- $file_ext = end(explode('.', $file_name));
- $file_rnd = substr(md5(uniqid()), mt_rand(0, 26), 6);
- $file_name = date('ymdhis').'_'.$file_rnd.'.'.$file_ext;
- }
- $file_name = $this->up_dir.'/'.$file_name;
- if (move_uploaded_file($up_file['tmp_name'], $file_name)) {
- $this->up_ret[] = str_replace(website_dirroot, '', $file_name);
- } else {
- exit('文件上傳失??!');
- }
- }
- }
- }
- } else {
- exit('未開啟寫入權限!');
- }
- } else {
- exit('上傳目錄創建失?。?#39;);
- }
- }
- public function getupload() {
- return emptyempty($this->up_ret) ? false : $this->up_ret;
- }
- function __destruct() {}
- }
- ?>
那么上傳的流程就是如下了:
1.給form標簽的enctype屬性賦值multipart/form-date,這個是必須的,而且也必須指定的,不然文件無法上傳.
2.判斷
這個判斷一般有三個判斷,一個是類型判斷,一個是大小判斷,一個是文件是否存在的判斷,因為這三個判斷是保證安全以及成功上傳的前提.
3.保存上傳的文件
因為文件上傳的時候都被存放在一個臨時的地方,所以要通過方法將其轉移到指定的地方,這樣調用也會很方便.
說了原理和流程,就是實際操作以及一些重要函數了,首先就是指定文件規定類型,但是不能直接指定,必須指定mime類型,不然php會報錯.
上傳的文件的信息一般都包含在一個叫$_files的關聯數組中,它包含了五方面的信息.
$_files['file']['name'] =>要上傳的文件的原名
$_files['file']['type'] =>要上傳的文件的類型
$_files['file']['size'] =>文件的大小
$_files['file']['tmp_name'] =>儲存的臨時文件名,一般是系統默認
$_files['file']['error'] =>上傳相關的錯誤代碼
錯誤代碼可以是一串數字,也可以是一些常量,比如0->upload_err_ok->上傳成功,你可以在這兒看到詳細的對應.
在轉移文件之前,最好使用is_uploaded_file()函數來測試臨時文件是否是通過http post上傳的,也可以檢測文件是否存在,一般用文件的臨時名作為參數,讓后就是使用move_uploaded_file()函數來轉移上傳的文件,這個函數有兩個參數,第一個是指定要轉移的文件,第二個是指定要轉移的文件,要轉移的文件一般是臨時文件,所以用臨時文件名(tmp_name)來指定,而第二參數一般也作為新的文件名,存進數據庫,以后就可以調用了.
這里要說的一個就是大文件上傳,在不借助第三方工具的情況下,可以通過設定php.ini的參數來完成,一個是upload_max_filesize,這個是指定上傳的最大限制,默認是2m,還有一個就是max_input_time,它指定了表單提交的最長時間限制,因為一般大文件上傳比較好時,所以這個也是必須的.
表單還可以有一些其他的控制,比如post_max_size是控制表單能接受的最大值,而memory_list可以指定每個php頁面能占有的最大內存,默認是8m,max_input_time可以指定每個php頁面接受數據的最長時間,默認是60秒.
新聞熱點
疑難解答