PHP文件上傳、錯誤處理

說明

這篇是針對以前php知識的補充內容php


一、 PHP目錄處理函數

處理文件夾的基本思想以下:
1.讀取某個路徑的時候判斷是不是文件夾
2.是文件夾的話,打開指定文件夾,返回文件目錄的資源變量
3.使用readdir讀取一次目錄中的文件,目錄指針向後偏移一次
4.使用readdir讀取到最後,沒有可讀的文件返回false
5.關閉文件目錄html

咱們來學習一比經常使用函數:linux

函數名 功能
opendir 打開文件夾,返回操做資源
readdir 讀取文件夾資源
is_dir 判斷是不是文件夾
closedir 關閉文件夾操做資源
filetype 顯示是文件夾仍是文件,文件顯示file,文件夾顯示dir
<?php
//設置打開的目錄是D盤
$dir = "d:/";

//判斷是不是文件夾,是文件夾
if (is_dir($dir)) {
   if ($dh = opendir($dir)) {


      //讀取到最後返回false,中止循環
      while (($file = readdir($dh)) !== false) {
           echo "文件名爲: $file : 文件的類型是: " . filetype($dir . $file) . "<br />";
       }

       closedir($dh);
   }
}
?>

二、 PHP文件權限設置

chmod 主要是修改文件的的權限web

<?php
//修改linux  系統/var/wwwroot/某文件權限爲755
chmod("/var/wwwroot/index.html", 755);  
chmod("/var/wwwroot/index.html", "u+rwx,go+rx"); 
chmod("/somedir/somefile", 0755); 
?>

三、 PHP文件路徑函數

咱們常常會遇處處理文件路徑的狀況。
例如:
1.文件後綴須要取出來
2.路徑須要取出名字不取目錄
3.只須要取出路徑名中的目錄路徑
4.或者把網址中的各個部份進行解析取得獨立值
5.甚至是本身組成一個url出來
... ....數據庫

不少地方都須要用路徑處理類的函數。windows

咱們把經常使用的路徑處理函數爲你們作了標註,你們對着這個路徑處理函數進行處理便可:數組

函數名 功能
pathinfo 返回文件的各個組成部份
basename 返回文件名
dirname 文件目錄部份
parse_url 網址拆解成各部份
http_build_query 生成url 中的query字符串
http_build_url 生成一個url
<?php
$path_parts = pathinfo('d:/www/index.inc.php');

echo '文件目錄名:'.$path_parts['dirname']."<br />";
echo '文件全名:'.$path_parts['basename']."<br />";
echo '文件擴展名:'.$path_parts['extension']."<br />";
echo '不包含擴展的文件名:'.$path_parts['filename']."<br />"; 
?>

四、 PHP實現文件留言本

咱們來看一下文件結構:
index.php ---展現輸入框和留言內容
write.php ---向message.txt寫入數據
message.txt ---存入聊天內容
index.php文件瀏覽器

<?Php
//設置時區
date_default_timezone_set('PRC');
//讀了內容
@$string = file_get_contents('message.txt');
//若是$string 不爲空的時候執行,也就是message.txt中有留言數據
if (!empty($string)) {
    //每一段留言有一個分格符,可是最後多出了一個&^。所以,咱們要將&^刪掉
    $string = rtrim($string, '&^');
    //以&^切成數組
    $arr = explode('&^', $string);
    //將留言內容讀取
    foreach ($arr as $value) {
        //將用戶名和內容分開
        list($username, $content, $time) = explode('$#', $value);
        echo '用戶名爲<font color="gree">' . $username . '</font>內容爲<font color="red">' . $content . '</font>時間爲' . date('Y-m-d H:i:s', $time);
        echo '<hr />';
    }
}
?>
<h1>基於文件的留言本演示</h1>
<form action="write.php" method="post">
    用戶名:<input type="text" name="username" /><br />
    留言內容:<textarea  name="content"></textarea><br />
    <input type="submit" value="提交" />
</form>

看了剛剛的展現內容,咱們知道文件存儲時:
1.段與段之間進行了分割
2.內容與用戶以前用一個特殊的符號進行了分割緩存

下面咱們來寫write.php寫入留言至文件的代碼:服務器

<?php
//追加方式打開文件
$fp=fopen('message.txt','a');

//設置時間
$time=time();

//獲得用戶名
$username=trim($_POST['username']);
//獲得內容
$content=trim($_POST['content']);


//組合寫入的字符串:內容和用戶之間分開,使用$#
//行與行之間分開,使用&^
$string=$username.'$#'.$content.'$#'.$time.'&^';

//寫入文件
fwrite($fp,$string);

//關閉文件
fclose($fp);


header('location:index.php');

?>

五、PHP文件上傳

在咱們平常使用中常常會遇到不少種這樣的狀況:
QQ空間裏面上傳圖片呀
微信朋友圈上傳圖片
發郵件裏面上傳郵件資料附件
認證的時候要求上傳照片或身份證

文件上傳須要注意php.ini文件

配置項 功能說明
file_uploads on爲 開啓文件上傳功能,off爲關閉
post_max_size 系統容許的POST傳參的最大值
upload_max_filesize 系統容許的上傳文件的最大值
memory_limit 內存使用限制

建議尺寸: file_size(文件大小) < upload_max_filesize < post_max_size < memory_limit
另外,須要注意的是腳本執行時間。
max_execution_time,這什參數的單位爲秒。
這個參數是設定腳本的最大執行時間。
也能夠根據需求作適當的改變。一般不須要來修改,系統默認值便可。超大文件上傳的時候,可能會涉及到這一項參數的修改。
上傳時間太長了,會超時。若是你將此項參數設爲0,則是不限制超時時間,不建議使。
完成了php.ini的相關配置,咱們就能夠開始試着完成第一次文件上傳了。

1. php文件上傳的步驟

系統返回的錯誤碼詳解

錯誤碼 說明
0 無誤,能夠繼續進行文件上傳的後續操做。
1 超出上傳文件的最大限制,upload_max_filesize = 2M php.ini中設置,通常默認爲2M。可根據項目中的實際須要來修改
2 超出了指定的文件大小,根據項目的業務需求指定上傳文件的大小限制
3 只有部分文件被上傳
4 文件沒有被上傳
6 找不到臨時文件夾,可能目錄不存在或沒權限
7 文件寫入失敗,可能磁盤滿了或沒有權限

注:錯誤碼中沒有5。

2. 自定義判斷是否超出文件大小範圍

在開發上傳功能時。咱們做爲開發人員,除了php.ini中規定的上傳的最大值外。 咱們一般還會設定一個值,是業務規定的上傳大小限制。
例如:
新浪微博或者QQ空間只准單張頭像圖片2M。而在上傳圖冊的時候又能夠超過2M來上傳。
因此說,它的系統是支持更大文件上傳的。
此處的判斷文件大小,咱們用於限制實際業務中咱們想要規定的上傳的文件大小。

3. 判斷後綴名和mime類型是否符合

在網絡世界裏面也有壞人。他們會把圖片插入病毒,在附件中上傳病毒,他們會在網頁中插入病毒或者黃色圖片。
咱們須要對於上傳的文件後綴和mime類型都要進行判斷才能夠。
MIME(Multipurpose Internet Mail Extensions)是多用途互聯網郵件擴展類型。是設定某種擴展名的文件用一種應用程序來打開的方式類型,當該擴展名文件被訪問的時候,瀏覽器會自動使用指定應用程序來打開。多用於指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。
在判斷後綴和MIME類型的時候,咱們會用到PHP的一個函數in_array(),該函數傳入兩個參數。
第一個參數是要判斷的值;
第二個參數是範圍數組。
咱們用這個函數來判斷文件的後綴名和mime類型是否在容許的範圍內。

4. 生成文件名

咱們的文件上傳成功了,不會讓它保存原名。由於,有些人在原名中有敏感關鍵詞會違反我國的相關法律和法規。咱們能夠採用date()、mt_rand()或者unique()生成隨機的文件名。

5. 判斷是不是上傳文件

文件上傳成功時,系統會將上傳的臨時文件上傳到系統的臨時目錄中。產生一個臨時文件。同時會產生臨時文件名。咱們須要作的事情是將臨時文件移動到系統的指定目錄中。
而移動前不能瞎移動,或者移動錯了都是不科學的。移動前咱們須要使用相關函數判斷上傳的文件是否是臨時文件。
is_uploaded_file()傳入一個參數($_FILES中的緩存文件名),判斷傳入的名稱是否是上傳文件。

6. 移動臨時文件到指定位置

臨時文件是真實的臨時文件,咱們須要將其移動到咱們的網站目錄下面了。
讓咱們網站目錄的數據,其餘人能夠訪問到。
咱們使用:move_uploaded_file()。
這個函數是將上傳文件移動到指定位置,並命名。
傳入兩個參數:
第一個參數是指定移動的上傳文件;
第二個參數是指定的文件夾和名稱拼接的字符串。

7. php文件上傳表單注意事項

**代碼以下:

1.index.html**

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標題文檔</title>
</head>
<body>
<h1>上傳文件</h1>
<form action="chuli.php" method="post" enctype="multipart/form-data">
請選擇文件:<input type="file" name="file" /><input type="submit" value="上傳" />
</form>
</body>
</html>

注意事項:
1.form 表單中的參數method 必須爲post。若爲get是沒法進行文件上傳的
2.enctype須爲multipart/form-data

2.chuli.php

<?php
//取文件信息
$arr = $_FILES["file"];
//var_dump($arr);
//加限制條件
//1.文件類型
//2.文件大小
//3.保存的文件名不重複
if(($arr["type"]=="image/jpeg" || $arr["type"]=="image/png" ) && $arr["size"]<10241000 )
{
//臨時文件的路徑
$arr["tmp_name"];
//上傳的文件存放的位置
//避免文件重複: 
//1.加時間戳.time()加用戶名.$uid或者加.date('YmdHis')
//2.相似網盤,使用文件夾來防止重複
$filename = "./images/".date('YmdHis').$arr["name"];
//保存以前判斷該文件是否存在
  if(file_exists($filename))
  {
    echo "該文件已存在";
  }
  else
  {
  //中文名的文件出現問題,因此須要轉換編碼格式
  $filename = iconv("UTF-8","gb2312",$filename);
  //移動臨時文件到上傳的文件存放的位置(核心代碼)
  //括號裏:1.臨時文件的路徑, 2.存放的路徑
  move_uploaded_file($arr["tmp_name"],$filename);
  echo "文件上傳成功";
  }
}
else
{
  echo "上傳的文件大小或類型不符";
}
?>

六、 PHP錯誤處理

在php.ini配置文件中。咱們能夠控制php的錯誤顯示狀態。php.ini中有一個專門的配置項:
display_errors
這個選項設置是否將錯誤信息輸出到網頁,或者對用戶隱藏而不顯示。
這個值的狀態爲on 或者 off,也能夠設值爲1 或者0。
display_error的值設爲0或者off則不在頁面中顯示錯誤,若是設爲1或者on則顯示錯誤信息。

問題:若是沒有修改服務器php.ini的狀態權限怎麼辦?
可使用ini_set。
<?php
ini_set('display_errors' , 0 );
?>
上面的代碼也至關於修改了php.ini中display_errors的值。不過,僅僅在當前php代碼中生效。

問題:想取得php.ini的配置項狀態怎麼辦?
可使用ini_get(參數項) 獲得參數的值。

<?php
echo '服務器中display_errors的狀態爲' . ini_get('display_errors');
?>

注:修改完php.ini文件,須要重啓服務器

1. php錯誤處理之錯誤報告級別

【掌握級別的錯誤類型】 咱們將最經常使用的錯誤分爲了三種:

錯誤類型 說明
E_ERROR 錯誤,文件直接中斷
E_WARNING 警告,問題比較嚴重。可是還會繼續向下運行
E_NOTICE 提示,有些小問題不會影響到程序。常發生在項目未定義
E_PARSE 編譯時語法解析錯誤。解析錯誤僅僅由分析器產生。
E_ALL 全部的錯誤
E_STRICT 啓用PHP對代碼的修改建議,以確保代碼具備最佳的互操做性和向前兼容性。
E_DEPRECATED 啓用後將會對在將來版本中可能沒法正常工做的代碼給出警告。

在上面的幾種類型中:
error最嚴重,必需要解決。否則程序沒法繼續向下執行
warning也很重要。通也必需要解決。若是明確的,故意的能夠不用處理。
notice 你能夠不用管。可是在有些公司,項目標準特別高。在高標準要求的項目中也必需要解決。由於,notice會影響到PHP的執行效率。一般發生在函數未定義等。
parse錯誤,是指語法錯寫錯了,必需要解決,表明所有類型的全部錯誤。

一、 在php.ini中error_reporting參數。如若error_reporting參數設置爲0。整個PHP引擎發錯誤均不會顯示、輸出、記錄。在下一章將要講到的日誌記錄中,也不會記錄。
若是咱們想顯示全部錯誤能夠寫上:
error_reporting = E_ALL
想要顯示全部錯誤但排除提示,能夠將這個參數寫爲:
error_reporting = E_ALL & ~ E_NOTICE
顯示全部錯誤,但排除提示、兼容性和將來兼容性。可寫爲:
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED

二、在有些狀況下咱們無權限操做php.ini文件,又想要控制error_reporting怎麼辦呢?
在運行的xxxx.php文件中開始處,咱們可使用error_reporting()函數達到目標。

<?php

//關閉了全部的錯誤顯示
error_reporting(0);


//顯示全部錯誤
//error_reporting(E_ALL);

//顯示全部錯誤,但不顯示提示
//error_reporting(E_ALL & ~ E_NOTICE);
?>

2. php錯誤處理之錯誤記錄日誌

在一些公司裏面,有專門的日誌收集系統。日誌收集系統會在背後默默的幫你收集錯誤、警告、提示。也有些公司沒有專門的日誌收集系統,經過文件來服務器當中的運行日誌。
其中:PHP的錯誤,警告這些是必需要收信的。那麼問題來了——不讓用戶看到,設置好錯誤報告級別好,如何將錯誤收集到日誌系統中呢?

這裏有須要使用到php.ini的相關配置項。這兩個配置項爲:

參數 配置項 說明
log_errors on/off 是否開啓日誌記錄
log_errors_max_len 整型,默認1024 單行錯誤最大記錄長度
error_log syslog或者指定路徑 錯誤日誌記錄在什麼地方

說明:
1.在表格中的log_errors和log_errors_max_len很是好理解。
2.而error_log 指定將錯誤存在什麼路徑上。配置項中的syslog可能有點不太好理解。syslog是指系統來記錄。windows系統在電腦的日誌收集器裏面。linux默認在: /etc/syslog.conf
[擴展] 瞭解知識點。若Linux系統啓動或修改了日誌收集。可能存儲在第三方專用的日誌收集服務器中。
此外,PHP還爲咱們專門準備了一個自定義的錯誤日誌函數:
bool error_log ( string $錯誤消息 [, int $錯誤消息類型 = 0 [, string $存儲目標]] )
這個函數能夠把錯誤信息發送到web服務器的錯誤日誌,或者到一個文件裏。

經常使用的錯誤消息類型

錯誤消息類型 說明
0 發送至默認的error_log指定位置
1 發送到指定的郵件位置
3 發送至指定的文件位置
<?php

//沒法鏈接到數據庫服務器,直接記錄到php.ini 中的error_log指定位置
error_log("沒法鏈接到數據庫服務器服務器");

//能夠發送郵件,可是php.ini必須配置過郵件系統
error_log('能夠用郵件報告錯誤,讓運維人員半夜起牀幹活',1 ,'pig@php.cn');

//記錄在指定的位置
error_log("我是一個錯誤喲", 3, "d:/test/my-errors.log");

?>

總結

以上就是今天要講的內容,本文僅僅簡單對以前PHP知識的一些補充,後面可能會用到。

相關文章
相關標籤/搜索