1. 程式人生 > >【php】檔案的上傳與下載

【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是檔案表單頁,沒什麼好說的,就一個表單:

<!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>
2、上傳處理頁upload.php,關鍵一個$_FILES["xx"],其中xx而是upload.html中的檔案域的name屬性,還有如何儲存上傳檔案的問題,儲存上傳檔案,必須利用$basepath=str_replace('\\','/',realpath(dirname(__FILE__).'/'))."/";取得伺服器的絕對路徑,整個思想與JSP中《【Servlet】利用Servlet3.0標準與JSTL表示式實現檔案上傳系統,支援圖片上傳後顯示》(點選開啟連結)是完全類似的,具體如下:
<?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);

?>