PHP檔案上傳、錯誤處理
說明
這篇是針對之前php知識的補充內容
目錄1、 PHP目錄處理函式
處理資料夾的基本思想如下:
1.讀取某個路徑的時候判斷是否是資料夾
2.是資料夾的話,開啟指定資料夾,返回檔案目錄的資源變數
3.使用readdir讀取一次目錄中的檔案,目錄指標向後偏移一次
4.使用readdir讀取到最後,沒有可讀的檔案返回false
5.關閉檔案目錄
我們來學習一比常用函式:
函式名 | 功能 |
---|---|
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); } } ?>
2、 PHP檔案許可權設定
chmod 主要是修改檔案的的許可權
<?php
//修改linux 系統/var/wwwroot/某檔案許可權為755
chmod("/var/wwwroot/index.html", 755);
chmod("/var/wwwroot/index.html", "u+rwx,go+rx");
chmod("/somedir/somefile", 0755);
?>
3、 PHP檔案路徑函式
我們經常會遇到處理檔案路徑的情況。
例如:
1.檔案字尾需要取出來
2.路徑需要取出名字不取目錄
3.只需要取出路徑名中的目錄路徑
4.或者把網址中的各個部份進行解析取得獨立值
5.甚至是自己組成一個url出來
... ....
很多地方都需要用路徑處理類的函式。
我們把常用的路徑處理函式為大家做了標註,大家對著這個路徑處理函式進行處理即可:
函式名 | 功能 |
---|---|
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 />";
?>
4、 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');
?>
5、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 "上傳的檔案大小或型別不符";
}
?>
6、 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錯誤,是指語法錯寫錯了,必須要解決,代表全部型別的所有錯誤。
1、 在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
2、在有些情況下我們無許可權操作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 ,'[email protected]');
//記錄在指定的位置
error_log("我是一個錯誤喲", 3, "d:/test/my-errors.log");
?>
總結
以上就是今天要講的內容,本文僅僅簡單對之前PHP知識的一些補充,後面可能會用到。