2009年1月13日 星期二

新建目錄與下載檔案寫法


//新建目錄
function create_dir($path) {
if (!file_exists($path)) {//如果文件夾不存在
create_dir(dirname($path)); //取得最後一個文件夾的全路徑返回開始的地方
mkdir($path, 0777);
return true;
}
}



//下載檔案
function download_file($file){

//First, see if the file exists
if (!is_file($file)) { die("404 File not found!"); }

//Gather relevent info about file
$len = filesize($file);
$filename = basename($file);
$file_extension = strtolower(substr(strrchr($filename,"."),1));

//This will set the Content-Type to the appropriate setting for the file
switch( $file_extension ) {
case "pdf": $ctype="application/pdf"; break;
case "exe": $ctype="application/octet-stream"; break;
case "zip": $ctype="application/zip"; break;
case "doc": $ctype="application/msword"; break;
case "xls": $ctype="application/vnd.ms-excel"; break;
case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
case "gif": $ctype="image/gif"; break;
case "png": $ctype="image/png"; break;
case "jpeg":
case "jpg": $ctype="image/jpg"; break;
case "mp3": $ctype="audio/mpeg"; break;
case "wav": $ctype="audio/x-wav"; break;
case "mpeg":
case "mpg":
case "mpe": $ctype="video/mpeg"; break;
case "mov": $ctype="video/quicktime"; break;
case "avi": $ctype="video/x-msvideo"; break;

//The following are for extensions that shouldn't be downloaded (sensitive stuff, like php files)
case "php":
case "htm":
case "html":
case "txt": die("Cannot be used for ". $file_extension ." files!"); break;

default: $ctype="application/force-download";
}

//Begin writing headers
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");

//Use the switch-generated Content-Type
header("Content-Type: $ctype");

//Force the download
$header="Content-Disposition: attachment; filename=".$filename.";";
header($header );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$len);
@readfile($file);
exit;
}

2009年1月12日 星期一

PHP 發送夾帶附件mail

郵件相關的東西。下面是一個帶附件(一個HTML文件)電子郵件的例子。
Return-Path: Date: Mon, 22 May 2000 19:17:29 +0000 From: Someone To: Person Message-id: <83729KI93LI9214@example.com> Content-type: multipart/mixed; boundary="396d983d6b89a" Subject: Here's the subject --396d983d6b89a Content-type: text/plain; charset=iso-8859-1 Content-transfer-encoding: 8bit
This is the body of the email.
--396d983d6b89a Content-type: text/html; name=attachment.html Content-disposition: inline; filename=attachment.html Content-transfer-encoding: 8bit

This is the attached HTML file

--396d983d6b89a--
  前面的7行是郵件的頭,其中值得注意的是Content-type頭部分。這個頭告訴郵件程序電子郵件是由一個以上的部分組成的。不含附件的郵件只有一個部分:消息本身。帶附件的電子通常至少由兩部分組成:消息和附件。這樣,帶兩個附件的郵件由三部分組成:消息,第一個附件和第二個附件。
  帶附件的電子郵件的不同部分之間用分界線來分隔。分界線在Content--type頭中定義。郵件的每個新部分以兩個連字號(--)和分界線開始。 最後一個分界線後也有兩個連字號,表示這個郵件中沒有其它的部分了。
  在每個分界線後有一些行,用來告訴郵件程序這個部分的內容的類型。 比如,看看上面例子中第一個分界線後面的兩行--以Content-type: text/plain開頭的行。這些行說明後面的部分是ISO-8859-1字符集的純文本。跟在第二個分界線後的行告訴郵件程序現在的部分是一個HTML文件,它的名字是"attachment.html"。
  Content-disposition這持告訴郵件程序如果可能就以內嵌的方式顯示附件。現在新的郵件程序會在消息後顯示HTML的內容。如果Content- disposition被設為attachment,那麼郵件程序就不會顯示HTML文件的內容,而是顯示一個連接到文件的圖標(或其它的類似的東西)。收件人要看附件的內容,必須點擊這個圖標。一般情況下,如果附件是一些文本(包含HTML),Content-disposition會被設為inline,這是因為現在大部分郵件程序能夠不借助其它瀏覽器而直接顯示附件(文本)的內容。如果附件不是文本(比如圖片或其它類似的內容),Content-disposition 就設為attachment。 我們仿照上面的例子,自己寫一個php程序,可以對提交的 收信人,發送人,信件內容,附件進行處理。
首先建立一個靜態頁面,代碼如下:























發送者:
接受者:
下載提示:
源數據文件:
 



要注意的是 : 表單裡 ENCTYPE="multipart/form-data" 一定要有。
再來看一下 發送郵件的php程序:

//文本內容
$text = $_POST['text'];
//標題
$subject = $_POST['subject'];
//發送者
$from = $_POST['from'];
//接受者
$to = $_POST['to'];
//附件
$file = $_FILES['upload_file']['tmp_name'];
// 定義分界線
$boundary = uniqid( "");
$headers = "Content-type: multipart/mixed; boundary= $boundary\r\n";
$headers .= "From:$from\r\n";
//確定上傳文件的MIME類型
if($_FILES['upload_file']['type'])
$mimeType = $_FILES['upload_file']['type'];
else
$mimeType ="application/unknown";
//文件名
$fileName = $_FILES['upload_file']['name'];

// 打開文件
$fp = fopen($file, "r");
// 把整個文件讀入一個變量
$read = fread($fp, filesize($file));
//我們用base64方法把它編碼
$read = base64_encode($read);
//把這個長字符串切成由每行76個字符組成的小塊
$read = chunk_split($read);
//現在我們可以建立郵件的主體
$body = "--$boundary
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8bit
$text
--$boundary
Content-type: $mimeType; name=$fileName
Content-disposition: attachment; filename=$fileName
Content-transfer-encoding: base64
$read
--$boundary--";
//發送郵件
if(mail($to, $subject,$body,$headers))
print "OK! the mail $from --- $to has been send
";
else
print "fail to send mail
";
?>

看不明白沒關係,我來說明一下:
  1,郵件頭的構造 :一般包括 內容類型(Content-type)要發送附件,設置為 multipart/mixed 意思是多個部分 (郵件本身+附件)。 boundary ,就是上面提到的分界線,他的值用php自帶的 uniqid();函數取得 接受方,抄送等,在後面加上 From: Cc:。與上面的 Content-type boundary 之間用 \r\n 分割 。
  2 郵件體 如果是純文本的郵件內容 它的格式如下: Content-type: text/plain; charset=iso-8859-1 Content-transfer-encoding: 8bit 後面再緊接著加上 郵件的文本內容。 如果是附件: Content-type: $mimeType; name=$fileName Content-disposition: attachment; filename=$fileName Content-transfer-encoding: base64 後面再緊接著加上 附件內容。 $mimeType 是附件的 MIME類型。 可以用 $_FILES['upload_file']['type'] 得到。 $fileName 就是附件的名字了 郵件文本內容和附件之間用 boundary 分割。 有人會問,附件內容是什麼?附件內容就是用read函數讀入所上傳的附件,然後再把它經過base64編碼之後再用chunk_split 大卸N塊,每塊大小是默認的76字符。 好了,現在再去看那段程序,應該沒什麼問題了吧?把相應的變量帶入mail函數里面就ok了。
以上程序在 PHP Version 4.3.8 freeBSD 下測試通過。