【php】檔案的上傳與下載
php檔案的上傳與下載其實不難的,就那麼的幾行程式碼,比起JSP的要簡單得多,具體可以參考:《【Servlet】利用Servlet3.0標準與JSTL表示式實現檔案上傳系統,支援圖片上傳後顯示》(點選開啟連結);《【Jsp】把Java寫到Respond輸出流裡面供使用者下載》(點選開啟連結);《【Struts2】檔案的上傳與上傳許可權的控制》(點選開啟連結);《【Struts2】中文檔案的下載與下載許可權的控制》(點選開啟連結),但是網上的資料眾說紛紜,還用來許許多多奇怪的函式,必須整理一下。
一、基本目標
設定一個檔案上傳系統,指定只能上傳少於1M的圖片,上傳之後提供此檔案的下載。
同時注意好本上傳下載系統的防範工作,直接輸入網址訪問兩個處理頁是不行的。這裡用到了《【php】使用重定向,偽裝表單處理頁面不存在》(
當然,自然能夠在上傳資料夾找到這張被改名的圖片,伺服器上的圖片一般不存中文的,改名成時間戳,後附上使用者資訊等。
二、基本準備
1、設定上傳與下載的系統之前,先開啟php目錄下的php.ini,如果通過《【php】本地開發環境的部署與helloworld》(點選開啟連結)一鍵在windows安裝php,則開啟..\php-5.2.14-win32下的php.ini-dist:
2、利用Ctrl+F查詢按鈕找到File Uploads那行,把file_uploads引數設定為On,隨便給一個臨時上傳資料夾給php,然後設定php最大上傳大小,當然,我們不是每次上傳都給這個最大限度給使用者,這個大小,只是像《【Struts2】檔案的上傳與上傳許可權的控制》(
3、在工程資料夾下新建一個upload資料夾去存放上傳的圖片,php找不到這個資料夾則拒絕上傳,當然,你可以自己寫程式碼新建。其基本目錄結構如下所示,upload.html是檔案表單頁,upload.php則是上傳處理頁,download.php則是下載處理頁。
三、製作過程
1、upload.html是檔案表單頁,沒什麼好說的,就一個表單:
2、上傳處理頁upload.php,關鍵一個$_FILES["xx"],其中xx而是upload.html中的檔案域的name屬性,還有如何儲存上傳檔案的問題,儲存上傳檔案,必須利用$basepath=str_replace('\\','/',realpath(dirname(__FILE__).'/'))."/";取得伺服器的絕對路徑,整個思想與JSP中《【Servlet】利用Servlet3.0標準與JSTL表示式實現檔案上傳系統,支援圖片上傳後顯示》(點選開啟連結)是完全類似的,具體如下:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>檔案上傳</title> </head> <body> <form action="upload.php" method="post" enctype="multipart/form-data"> <input type="file" name="file" /> <input type="submit" name="submit" value="提交" /> </form> </body> </html>
<?php
//看是否是通過正常途徑傳遞一個file過來了
if(empty($_FILES["file"])){
//如果不是,則非正常開啟此頁
header("location: error.php");
exit;
}
else{
header("Content-type: text/html; charset=utf-8");
}
//這是判斷是否上傳的file
$canUpload=true;
//這樣就能夠取得上傳的檔名
$fileName=$_FILES["file"]["name"];
//通過對$fileName的處理,就能夠取得上傳的檔案的字尾名
$fileExtensions=strrchr($fileName, '.');
//這樣就能夠取得上傳檔案的大小
$fileSize=$_FILES["file"]["size"];
//即將被列印的錯誤資訊
$errmsg="";
//這裡是檔案的異常,一般不會出現
if($_FILES["file"]["error"]>0){
$errmsg .= "異常:".$_FILES["file"]["error"]."!";
$canUpload=false;
}
//如果上傳的檔名的字尾不是以下的幾種則不能上傳
if($fileExtensions!=".bmp" && $fileExtensions!=".gif" && $fileExtensions!=".jpg" && $fileExtensions!=".jpeg" && $fileExtensions!=".png"){
$errmsg .= "只能上傳圖片型別!字尾名必須為:.bmp,gif,jpg,jpeg,png任一!";
$canUpload=false;
}
//如果上傳的檔案大於1M則也不能上傳
if($fileSize>1*1024*1024){
$errmsg .= "檔案太大!請少於1M!";
$canUpload=false;
}
//如果檔案可以上傳
if($canUpload==true){
//儲存在伺服器的名字則是時間戳,加檔案字尾名
$saveName=time().$fileExtensions;
//取得伺服器的目錄的絕對路徑。
$basepath=str_replace('\\','/',realpath(dirname(__FILE__).'/'))."/";
//然後則儲存這個上傳檔案
move_uploaded_file($_FILES["file"]["tmp_name"],$basepath."/upload/".$saveName);
echo $fileName.",上傳成功!大小:".($fileSize/1024)."KB";
//把儲存在伺服器的名字傳到下載頁,供其處理
echo "<a href='download.php?saveName=$saveName'>下載</a>";
}
else{
echo $errmsg."<a href='upload.html'>返回</a>";
}
?>
3、下載處理頁download.php,這一頁其實不寫,可以正常顯示圖片的,但是通過把物件拋到respond物件中給使用者下載,則可以提出一個下載提示框。整個思想還是與《【Jsp】把Java寫到Respond輸出流裡面供使用者下載》(點選開啟連結)一樣,只是寫作語言不同而已。
<?php
//防止輸入網址直接訪問
if(empty($_REQUEST["saveName"])){
header("location: error.php");
exit;
}
else{
header("Content-type: text/html; charset=utf-8");
}
//取得儲存在伺服器的名字
$fileName=$_REQUEST["saveName"];
//取得伺服器的絕對路徑
$basepath=str_replace('\\','/',realpath(dirname(__FILE__).'/'))."/";
$filepath=$basepath."upload/".$fileName;
//讀取這個資料夾,構造下載流
$fp=fopen($filepath,"r");
//返回檔案給Respond物件,給使用者下載
header("Content-type: application/octet-stream");
//取出檔案大小,還是用於構造Respond物件
$filesize=filesize($filepath);
header("Accept-Length: ".$filesize);
//按照位元組格式返回
header("Accept-Ranges: bytes");
//彈出客戶端對話方塊,對應的檔名
header("Content-Disposition: attachment; filename=".$fileName);
//這樣就不會有檔案分段,導致檔案下載之後損壞的問題的
$buffer=1024;
while(!feof($fp)){
$file_data=fread($fp,$buffer);
echo $file_data;
}
//關閉檔案
fclose($fp);
?>