2008年12月9日

PHP+MS SQL Server 寫入Image型態資料

SQL Server有Image的欄位型態,在開發Desktop Application若需要讓使用者儲存圖片,例如大頭照、產品圖片,這時候很常將欄位設定Image型態,在使用整合型的開發工具時,通常只需要做些設定,圖片就能夠順利存取。但如果用PHP寫網頁程式,需要存取這個欄位,就需要多做一些處理。若使用的函式庫有支援Binary資料的存取功能,那只要呼叫這些函式即可解決。比較棘手的情況是,當我們只能下純文字的SQL去存取資料庫時,就必須自己動手克服。

顯示圖片比較簡單,通常只要將查詢的結果dump出來,例如:
showpic.php
$db->query("select content from images where id = 1");
$pic = $db->fetch()->content;
echo $content;

show.html
<img src="showpic.php" />

上傳圖片需要編碼處理,例如我們先用$_FILES取得上傳的圖片資訊:
$name = $_FILES['picfile']['name'];
$tmp_name = $_FILES['picfile']['tmp_name'];

接著將上傳的暫存檔案(即圖片檔)內容全部讀出來(file_get_contents的預設flag是FILE_BINARY,不會有問題)。
$c = file_get_contents($tmp_name);

再來,必須先將圖片內容以HEX編碼轉換成字串(即十六進位表示法)。
$content = "0x";
for ($i=0; $i<strlen($c); $i++) {
  $h = dechex(ord($c[$i]));
  if (strlen($h)<2) $h = '0'.$h;
  $content .= $h;
}

編碼後產生的字串格式…
0x112233445566778899AABBCCDDEEFF

解說:
從圖片檔讀取每一個byte,其ASCII的值範圍是0~255,也就是需要2^8來表示(即8個bit),轉成十六進位必須要16^2表示,也就是每個byte需要儲存成兩個16進位的字元符號,所以轉換的結果以固定每兩個十六進位字元符號來表示一個byte資料的值。例如255就是FF,而10就是A,而A只用了一個字元符號,必須在前面補0變成0A。

轉換之後,要寫入資料庫就跟平常的SQL並無不同。
$db->query("insert into images(name, content) values('$name', $content)";

唯一需要注意的是,範例程式碼中的$content並不需要加上單引號,因為開頭的0x已經宣告這是一串十六進位表示的資料,若加上單引號則會被當作字串,反而會出現型態不符的警告。

沒有留言:

張貼留言

lyhcode by lyhcode
歡迎轉載,請務必註明出處!