Sunday, May 15

[WEB] php 夾帶檔案 email 程式

這篇文章分成三部分:
  1. 在上傳網頁內加入夾帶檔案的表單;
  2. 寄件程式;
  3. 用 mySQL 管理夾帶檔案。
由於會用到一些 MIME(Multipurpose Internet Mail Extensions) 的概念,建議可以先到 Wikipedia 參考一下相關條目

第一部分:檔案上傳

上傳檔案:<input type="file" name="uploadedfile">
<input type="Button" value="上傳" onclick="tformsubmit();">

以上是 html 表單的部分,uploadedfile 是上傳檔案的預設變數。onclick 在這邊是指向另一個 javascript 已提醒上傳者確認這個動作。Javascript 如下:

if(confirm("確認送出資料嗎!?")){
tf["act"].value="submit";
tf.submit();}
也就是說,如果不要這麼麻煩的話,直接在 onclick 動作那一欄裡寫 submit 就可以了。這個表單在 html 裡是有內建的 function,所以簡簡單單就可以弄出像下面的成果:

上傳檔案的表單外觀
接下來是 php 的部分:

$filename = basename( $_FILES['uploadedfile']['name']);
$target_path = "目的資料夾路徑".$filename;
move_uploaded_file($_FILES['uploadedfile']['tmp_name'],
$target_path);

$filename 變數儲存所上傳的檔案「名稱」,也就是客戶端的路徑不會被顯示出來,不過這個 $_FILES 家族其實是一個 php 內建的陣列,裡面還存有其他跟上傳以後的檔案有關的資訊,有需要的話也可以再回頭參考看看需要哪個元素。$target_path 儲存了你希望把上傳的檔案從暫存資料夾(tmp/)轉存到 server 上其他資料夾的路徑。也就是說,在 move_uploaded_file 這個函式執行過以後,原本在暫存資料夾裡的上傳檔案就會被移到永久資料夾裡了。如果不另外指定目的資料夾路徑,檔案會被移到 php 程式所在的資料夾裡。

這樣一來檔案上傳就算完成了。但是傳到伺服器上的檔案並不能直接以 php 程式寄出,必須先轉換成 base64 的格式,所以還要在加上一行程式:

$file=chunk_split(base64_encode(file_get_contents
($target_path)));
把檔案變成 binary 字串,以供稍後的 MIME type 解讀。這行程式是下面 php 程式的一部分。


第二部分:自動寄發email

這部分的話,主要是使用以下的程式:

<?php
//設定你的收件者email
$to = '收件者email';
//寄件主旨
$subject = 'Test email with attachment';
//如果要寄中文的 email 主旨,必須用這個程式碼:$subject= "=?BIG5?B?".base64_encode('主旨')."?="; 中文主旨才能正確出現.同理,寄件人名稱如果要顯示成正體中文,也要用 "=?BIG5?B?".base64_encode('寄件者')."?=" 把寄件者資訊轉換成電腦可以讀的 base64 encode 格式.
//建立 MIME 邊界字串(boundary string), 這邊用 MD5 演算法自動產生隨機 hash, 但如果你確定在 email 內容不會出現相同的字串, 可以自己設定想要的字串
$random_hash = md5(date('r', time()));
//Header設定.需以\r\n加入換行符號
$headers = "From: 寄件者email\r\nReply-To: 回信地址";
//在header加入MIME邊界定義的延伸內容, 最開頭的\r\n一樣是換行符號
$headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\"";
//將夾帶檔案轉成字串形式
//並以MIME base64方式解碼後轉成較短的字串 $file=chunk_split(base64_encode(file_get_contents ($target_path)));

郵件內容部分有一點要特別注意,在複製程式碼到你的網頁以後,要確認所有 MIME code 都緊鄰視窗左邊,也就是在每一行敘述前都不能有空白,這也是為什麼在以下範例中會在第一行直接換行。同時也要確認每個 boundary 後面都沒有空白或是換行符號。這一點在複製程式碼到自己的網頁檔中時很容易忽略。

$body= " --PHP-mixed-$random_hash
Content-Type: multipart/alternative; boundary=\"PHP-alt- ".$random_hash."\"

--PHP-alt-$random_hash
Content-Type: text/html; charset='big5'
Content-Transfer-Encoding: 8bit
".email文字內容."
--PHP-alt-$random_hash--";

$body.=" --PHP-mixed-$random_hash
Content-Type: application/pdf; name=\"".$filename."\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment ".$file." --PHP-mixed-$random_hash--";

上述的 php 程式中,第一個 $body 的部分使用 BIG5(繁體中文)編碼,可以顯示文字部分的內容,到了下面連接的 $body. 部分,content type 就改成 application/pdf,後面 name 的地方會在 email 裡顯示夾帶檔案的名稱。application/ 的 MIME type 有很多種,可以參考 W3school 的表格選擇你要的檔案形式。等我以後把自動轉換的程式寫出來再跟大家分享吧(毆)。這樣內文就完成了。 最後是發送 email:

set_time_limit(0); //不逾時
$ol_email= email地址陣列; for($i=1;$i<count($ol_email);$i++){ $email=$ol_email[$i]; echo "=> [".$email."]<br>";
@mail($email, 主旨, $body, $Headers);

set_time_limit 函式內的數字是以秒為單位,如果不加這一行,預設是 30 秒後發送。另外有需要的話,可以在 php.ini 裡把預設時間改掉,該函式為 max_execution_time。email 地址陣列可以是資料庫(下面會說明),或是在 php 程式中建立的陣列。@mail 函式會將 email 寄出。主旨的地方記得要更改喔!


第三部分:用 mySQL 管理夾帶檔案

這部分介紹一下用 mySQL 儲存夾帶檔案並且自動嵌入 email 內容的方法。其實原理很簡單,就是把

$file=chunk_split(base64_encode(file_get_contents
($target_path)));

這部分的 $file 變數改成陣列的內容,之後再把整個陣列更新到資料庫裡就可以了。等要讀取的時候,再把資料庫的 binary string 指定到

--PHP-mixed-$random_hash
Content-Type: application/pdf; name=\"".$filename."\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment".$file."
--PHP-mixed-$random_hash--";


的 $file 就可以了。同時記得要把上面 $file 的定義改掉。另外還有一點很重要,attachment 與 $file 變數中間一定要有一行空行,不然寄出的檔案是無法被收件程式自動轉換成可讀的檔案的.

關於更新和呼叫 mySQL 內容的方法,之後會再說明。

No comments :

Post a Comment