LưunộidungfileảnhvàoCSDL MYSQL
Nhu cầu phát triển web của PHP là lưunộidung của fileảnhvào trong một cơ sở dữ liệu (CSDL)
và sau đó là đọc nộidung của fileảnh đã lưu trong CSDL ra và hiển thị ra trình duyệt. Nhu cầu
này có một số đặc điểm sau:
TỔNG QUAN
Nhu cầu phát triển web của PHP là lưunộidung của fileảnhvào trong một cơ sở dữ liệu (CSDL)
và sau đó là đọc nộidung của fileảnh đã lưu trong CSDL ra và hiển thị ra trình duyệt. Nhu cầu
này có một số đặc điểm sau:
● LưunộidungfileảnhvàoCSDL thì sẽ không phụ thuộc vào đường dẫn đến thư mục chứa
hình. Nếu bạn dùng theo cách hiển thị nộidung hình ảnh theo cách truyền thống thì đường đến
file hình thật chính xác thì file hình mới hiển thị ra, chẳng may thư cấu trúc thư mục đó bị thay đổi
thì chúng ta phải cập nhật lại rất nhiều đường dẫn trên website, hay fileảnh có thể bị xóa mất
hay bạn restore hay backup bị thiếu Chỉ thiếu một phần nhỏ là file hình không hiển thị được rồi.
Để giảm được những rủi ro này bạn dùng cách như thế này là lưunộidungfileảnhvàoCSDL
như vậy là không phụ thuộc vào đường dẫn hay cấu trúc thư mục rất là lôi thôi. Chúng ta chỉ
phụ thuộc vàonơi chứa nộidung chủa file hình.
● Lưu nộidungfileảnh vào CSDL thì rất thuận tiện cho việc backup và restore. Trong đó dùng
cách truy cập trực tiếp đến hình thì khi backup hay restore thì chúng ta phải backup/restore rất
nhiều file nhỏ rất là mệt. Trong khi đó dùng cách lưu nộidungfileảnh vào CSDL thì chúng ta chỉ
cần backup/restore lại một file là đủ, thông thường là file SQL.
● Nếu chúng ta dùng cách truy cập trực đến file hình thì khi chúng ta upload hình lên server qua
(form upload) thì một số host không cho ta quyền ghi vào thư mục (write) thì chúng ta không đưa
hình lên trang web của mình được. Lưufile trong CSDL là một giải pháp khá thích hợp trong
hoàn cảnh này.
● Không chỉ lưu giới hạn fileảnhvàoCSDL mà chúng ta còn lưu rất nhiều file khác nhau vào
CSDL. Để đơn giản chúng ta sẽ tìm hiểu cách lưufileảnhvàoCSDLMySQL và ngôn ngữ thực
hiện là PHP.
THIẾT KẾ CSDL
Chúng ta chỉ cần một bảng để lưunộidung của một fila ảnh và trong bảng này chúng ta sẽ thiết
kế như sau:
● Cột nhận dạng (ID) của file ảnh, chúng ta dùng kiểu dữ liệu AUTO_INCREMENT để làm ID cho
các fileảnh đã lưu trong CSDL.
● Cột lưu nộidungfile ảnh, đây là cột quan trọng quyết định hình ảnh sẽ hiển thị lên trình duyệt.
Nội dung của fileảnh cũa là một chuỗi nhưng dữ liệu nhị phân. Vì vậy chúng ta sẽ sử dụng kiểu
dữ liệu mediumblob để lưunộidung của fileảnh (kiểu dữ liệu blob cũng là chuỗi nhị phân, nhưng
chiều dài tối đa chỉ có 65Kb, sẽ không đủ cho chúng ta muốn lưu một fila ảnh lớn).
● Và bảng chúng ta sẽ có cấu trúc như sau
CREATE TABLE imgData (
imgID int NOT NULL AUTO_INCREMENT,
imgContents mediumblob NOT NULL,
PRIMARY KEY (imgID)
);
LƯU NỘIDUNGFILEẢNH VÀO CSDL
Chúng ta xem như đã có trên server. Và đoạn chương trình sau sẽ mở fileảnh thông qua tên file
để đọc nộidung của fileảnh và lưu nộidungfileảnh vào trong CSDL.
//connect vàoCSDL MySQL
//host = localhost
//username = root
//password = root
$conn = mysql_connect("localhost", "root", "root");
//chọn database làm việc
mysql_select_db("imgSave", $conn);
//tên file ảnh
$imgFilename = "imgData.jpg";
//mở fileảnh để đọc với chế độ đọc binary
$f = fopen($imgFilename, "rb");
$imgContents = fread($f, filesize($imgFilename));
fclose($f);
//chèn nộidungfileảnhvào table imgConetnts
$sql = "INSERT INTO imgData (imgContents) VALUES('" .
mysql_real_escape_string($imgContents, $conn) . "')";
mysql_query($sql, $conn);
?>
ĐỌC NỘIDUNGFILEẢNH TỪ CSDL
Để đọc nộidung của fileảnh từ CSDL, ta cần ID của fileảnh nếu chúng ta muốn hiển thị tấm
hình nào. Đoạn mã sau sẽ minh hoạ chi tiết, nhưng ở đây ta chỉ lấy 1 tấm hình có chỉ số ID = 1.
//connect vàoCSDL MySQL
//host = localhost
//username = root
//password = root
$conn = mysql_connect("localhost", "root", "root");
//chọn database làm việc
mysql_select_db("imgSave", $conn);
//ID của file ảnh
$imgID = 1;
//đọc nộidungfileảnh từ table tblImage
$sql = "SELECT * FROM imgData WHERE imgID=" . $imgID;
$result = mysql_query($sql, $conn);
while($row = mysql_fetch_array($result)){
$imgData = $row['imgContents'];
}
?>
Biến $imgData sẽ chứa nộidung của file ảnh. Bước tiếp theo, ta xuất nộidung của fileảnh ra
browser. Quá trình xuất nộidung của fileảnh ra browser. Nhưng chúng ta phải báo cho Browser
biết nộidung của chúng ta xuất ra là hình ảnh, đơn giản là chúng ta chỉ chèn vào một dòng
header("Content-type: image/jpeg"); là được. Và sau đây là quy trình xuất ra nộidung một file
ảnh như sau.
header("Content-type: image/jpeg");
echo $imgData;
?>
Như bạn đã thấy rồi đó lưufileảnhvàoCSDL và đọc nộidung của một fileảnh từ CSDL để xuất
ra Browser thật là không dễ chút nào. Nhưng chúng ta chỉ cần lưu ý các bước sau đây.
· Đọc nộidungfilevào 1 biến, bạn nhớ phải mở file với chế độ đọc binary.
· Xử lý các ký tự đặc biệt trước khi lưuvào database (sử dụng hàm mysql_real_escape_string).
· Trước khi xuất nộidungfile ra browser, bạn nhớ dùng hàm header để báo cho browser biết kiểu
file mà chương trình của bạn chuẩn bị trả về là một file ảnh.
KẾT LUẬN
Chúng ta có thể dùng cách này để viết một chương trình quản lý download trên website của
mình. Tuy nhiên chúng ta cũng cần có một vài điều chú ý như sau:
· Làm như vậy thì server sẽ xử lý nhiều công việc hơn cách download file trực tiếp.
· Tốc độ download sẽ chậm hơn rất nhiều so với download file trực tiếp.
· Nộidungfile thì được lưu trữ trong CSDL mà CSDL cho số lượng người kết nốivào có hạn,
trong khí đó với 1 file có dung lượng lớn thì chúng ta có thể mất rất nhiều thời gian để download
MỘT THÍ DỤ VỀ CHƯƠNG TRÌNH DOWNLOAD
Giả sử chúng ta có 1 file example.zip nằm trong cùng một thư mục với file download.php. Nhưng
chỉ người viết mới biết là file này nằm ở đâu, người truy cập muốn lấy file example.zip về thì phải
truy cập vào trang download.php và trang download.php sẽ có nộidung như sau:
//file download.php
$filename = "example.zip";
$f = fopen($filename, "rb");
header("Content-type: application/octet-stream");
header("Content-length: " . filesize($filename));
fpassthru($f);
fclose($f);
?>
Chúng ta chỉ cần bấy nhiêu là hoàn thành một trang download. Nhưng nếu muốn cho trang
download chúng ta đẹp hơn, hoàn thiện hơn thì chúng ta phải cải tiến thêm.
Giải thích những câu lệnh trên
Đầu tiên, ta mở file example.zip để đọc ở chế độ nhị phân (binary):
$f = fopen($filename, "rb");
Tiếp theo ta báo cho browser biết data trả về từ server là dữ liệu nhị phân chứ không phải là văn
bản HTML như thông thường:
header("Content-type: application/octet-stream");
Đồng thời ta cũng báo cho browser biết dung lượng của file sẽ được tải xuống:
header("Content-length: " . filesize($filename));
Và cuối cùng là đọc nộidungfile và echo lại cho browser download:
fpassthru($f);.
Lệnh fpassthru($f); tương đương với 2 lệnh:
$content = fread($f, filesize($filename));
echo $content;
Và như thế chúng ta có thể thí dụ chạy trên nhiều kiểu file khác nhau như (word, excel, PDF )
và bạn sẽ thấy có một vài chỗ thật khó chịu vì browser mặc định sẽ lưufile của bạn lên đĩa với
tên là download.php bạn phải đổi tên lại cho đúng và trước khi mở file đó ra đọc.
Để giải quyết vấn đề trên ta chỉ cần thêm một lệnh header() nữa là được.
header('Content-disposition: attachment; filename="'.$filename.'"');
Tham số "attachment" của header "Content-disposition" sẽ báo cho browser biết là nên download
và save file thay vì open. Tham số "filename=" sẽ báo cho browser biết tên của file đang được
download.
Tới đây chúng ta có thể nâng cấp trang web của mình lên cho người dùng chọn file để download.
Có nghĩa là chúng ta hiển thị ra 1 list các tập tin cho người dùng download và liên kết các file
download đều đến file download.php?filename=”Tên file cần download”. Trong file download.php
chỉ cần $_GET['filename'] là chúng ta có thể download về được.
Và file download.php sẽ có nộidung như sau:
$filename = isset($_GET['file'])?$_GET['file']:'';
$upload_dir = " /upload/";
//Mở file với chế độ nhị phân
$fp = fopen($upload_dir.$filename, "rb");
//gởi header đến cho browser
header('Content-type: application/octet-stream');
header('Content-disposition: attachment; filename="'.$filename.'"');
header('Content-length: ' . filesize($upload_dir.$filename));
//đọc file và trả dữ liệu về cho browser
fpassthru($fp);
fclose($fp);
. Lưu nội dung file ảnh vào CSDL MYSQL
Nhu cầu phát triển web của PHP là lưu nội dung của file ảnh vào trong một cơ sở dữ liệu (CSDL)
và sau đó là đọc nội.
các file ảnh đã lưu trong CSDL.
● Cột lưu nội dung file ảnh, đây là cột quan trọng quyết định hình ảnh sẽ hiển thị lên trình duyệt.
Nội dung của file ảnh