Disneyland 1972 Love the old s

CuDemVN.Wap.Sh

- GetSmile.Mobie.In - Diễn đàn chia sẻ Cú đêm Việt Nam
- AiChat.Wap.Sh - Diễn đàn Xtgem Việt Nam
- HamTruyen.Xtgem.Com - Blog Ham Truyện nơi hội tụ của những tín đồ mê truyện chữ
* Trang chủ >> WapMaster
Tìm Kiếm Thảo Luận
↓↓

Tìm kiểu hàm Header trong PHP và cách viết Một chương trình download đơn giản để giấu link thật đến file

Admin* RoSino18k *
* 10-08-2017
Có lẽ cũng không cần giới thiệu nhiều về nhu cầu "giấu giếm" này vì hiện nay có khá nhiều site sử dụng cách quản lý download như vậy và cũng có số lượng cũng nhiều không kém các site mới muốn tìm hiểu và sử dụng nó ngon . Tuy nhiên, có lẽ không thừa nếu như chúng ta tìm hiểu kỹ hơn một chút về lý do sử dụng một chương trình download manager trên website để giấu đường dẫn thực sự đến các file download.

Quản lý băng thông và "tài sản" là 2 lý do chính để sử dụng 1 chương trình quản lý download trên website. Bạn thử tưởng tượng có 1 website cho download nhạc hoặc ebook với 1 mức phí nho nhỏ, nếu mà link để download trực tiếp các file bị lộ tùm lum thì thứ nhất là "lỗ vốn", thứ hai là bandwidth sẽ hết sạch nhanh đến nỗi trước khi bạn kịp hiểu chuyện gì đã xảy ra.
Một số lý do khác cũng "chính đáng" không kém ví dụ như bạn muốn đếm số lần download file, hoặc website của bạn tự upload file của mình lên và các file này lại nằm trong database hoặc được để trong 1 thư mục mà từ ngoài web không đọc được. Trong những trường hợp như vậy, sử dụng 1 chương trình quản lý download trên website sẽ khá tiện lợi.

Tìm kiểu hàm Header trong PHP và cách viết Một chương trình download đơn giản để giấu link thật đến file
[Tải ảnh]


Tuy nhiên, cũng có vài điều cần chú ý trước khi bạn quyết định sử dụng 1 chương trình quản lý download trên website của mình:
- Tốc độ download sẽ chậm hơn rất nhiều so với download file trực tiếp.
- Server sẽ phải xử lý nhiều công việc hơn so với khi cho phép download file trực tiếp.
- Nếu file được lưu trữ trong database, bạn nên chú ý rằng số lượng kết nối đồng thời vào database là có hạn, trong khi với 1 file có dung lượng lớn, có thể phải mất tới nửa tiếng hoặc hơn để download.

Hướng dẫn viết Chương trình quản lý download - Download File Manager:
Giả sử bạn có 1 file document.zip trong cùng thư mục với file download.php. Nhưng chỉ mình bạn biết là file document.zip này nằm ở đâu, người khác muốn download thì phải truy cập vào file download.php của bạn. Mã nguồn của file download.php sẽ như sau:
//file download.php
<?php
$filename = "document.zip";
$fp = fopen($filename, "rb");
header("Content-type: application/octet-stream");
header("Content-length: " . filesize($filename));
fpassthru($fp);
fclose($fp);
?>

Ủa, chỉ có nhiêu đó thôi à? Đúng vậy, chỉ có vỏn vẹn 10 dòng là có được 1 chương trình download manager đơn giản (dĩ nhiên là chương trình này chỉ cho phép download được mỗi 1 file document.zip, ta còn phải làm việc nhiều để cho chương trình hoàn thiện hơn!).

Giải thích code:
Đầu tiên, ta mở file document.zip để đọc ở chế độ nhị phân (binary):
$fp = 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ội dung file và echo lại cho browser download:
fpassthru($fp);

Lệnh fpassthru($fp); tương đương với 2 lệnh:
$content = fread($handle, filesize($filename));
echo $content;

Như vậy chương trình này cũng không có gì khác với các chương trình PHP thông thường ngoài 2 lệnh header(). Trong đó lệnh:
header("Content-length: " . filesize($filename));

cũng không có gì là khó hiểu, lệnh này báo cho browser biết dung lượng của file chuẩn bị download (thực ra không có lệnh này thì quá trình download vẫn diễn ra như bình thường). Vấn đề mấu chốt nằm ở lệnh:
header("Content-type: application/octet-stream");

Lệnh này sẽ báo cho browser biết là dữ liệu chuẩn bị load xuống là dữ liệu nhị phân. Vì là dữ liệu nhị phân nên browser sẽ thực hiện quá trình download và save file thay vì hiển thị lên browser như là 1 trang HTML thông thường.

Thử chạy ví dụ trên vài lần, thay thế file document.zip bằng một số file khác nhau (ví dụ file Word, PDF, Excel...) và thử trên vài browser khác nhau, bạn sẽ nhận thấy có vài chỗ hơi khó chịu:
- Browser sẽ mặc định lưu file lên đĩa với tên là download.php. Bạn phải đổi tên file lại cho đúng trước khi mở file ra đọc.
- Trong một số trường hợp, thay vì hỏi save file lên đĩa, browser sẽ mở luôn file (ví dụ chạy Word hoặc Acrobat mở luôn file vừa được download).

Để giải quyết 2 vấn đề khó chịu trên cũng không có gì khó khăn lắm, ta chỉ cần thêm 1 lệnh header() nữa:
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.

Tiếp tục cải tiến chương trình:
Cho tới bây giờ chương trình của chúng ta vẫn còn thô sơ, chúng ta vẫn cần them vào chức năng nữa để chương trình hoàn thiện hơn. 

Cho phép người dùng chọn file để download. Hiện tại chương trình của chúng ta chỉ mới cho phép download 1 file duy nhất.
Kiểm tra dữ liệu nhập từ người dùng. Đây là một việc luôn nên làm. Chương trình cho phép người dùng chọn file để download thì cũng cần nên kiểm tra kỹ kẻo chính file config, file source hoặc file password của bạn bị download thì phiền.

Cho phép người dùng chọn file để download: Thao tác này có lẽ khá đơn giản đối với bạn. Chương trình sẽ nhận vào tham số file từ URL (ví dụ: download.php?file=document.zip). Đoạn code xử lý như sau:
$filename = isset($_GET['file'])?$_GET['file']:'';  

Kiểm tra dữ liệu nhập: Ta cần kiểm tra các điều kiện sau:
- File có tồn tại và được phép đọc hay không? PHP cung cấp sẵn cho ta 2 hàm ls is_file() và is_readable() để làm việc này:
if ( $filename == "" || !is_file($filename) || !is_readable($filename) ) {
    echo "Error: ...";
    exit(-1);
}

Đoạn mã trên sẽ kiểm tra nếu như tên file là rỗng, hoặc file không tồn tại hoặc không đọc được thì sẽ báo lỗi và thoát.
- Tên file có chứa các ký tự đặc biệc hay không? Thường các file upload sẽ được để trong 1 thư mục riêng. Như vậy tên file chỉ có thể chứa các ký tự a-z, 0-9, gạch ngang (-), gạch dưới (_), khoảng trắng và dấu chấm (.). Ta có thể xem như các kỹ tự khác trong tên file là không hợp lệ. Đoạn mã kiểm tra như sau:
if ( !preg_match('/^[a-z0-9\_\-\. ]*$/i', $filename) ) {
    echo "Error: ...";
    exit(-1);
}

Đoạn mã trên sẽ kiểm tra nếu như trong file có chứa ký tự lạ (không phải là 0-9, a-z, gach dưới, gạch ngang, khoảng trắng, dấu chấm, khoảng trắng thì sẽ báo lỗi) và thoát chương trình. Ngoài ra, có một số file cấu hình đặc biệt của server được bắt đầu bằng dấu chấm (ví dụ .htaccess, .htpasswd), ta cũng phải kiểm tra xem ký tự đầu tiên của tên file có phải là dấu chấm hay không, nói cách khác, ký tự đầu tiên của tên file phải là 1 chữ cái (a-z) hoặc chữ số (0-9) hoặc kỹ tự gạch ngang hoặc gạch dưới. Lệnh if trên được cải tiến lại như sau:
if ( !preg_match('/^[a-z0-9\_\-][a-z0-9\_\-\. ]*$/i', $filename) ) {
    echo "Error: ...";
    exit(-1);
}

Ghép lại ta có chương trình được cải tiến như sau:
<?php
//các file upload được để trong 1 thư mục riêng
$upload_dir = "../upload/";
 
//lấy tên file cần download từ URL
$filename = isset($_GET['file'])?$_GET['file']:'';
 
//thực hiện quá trình kiểm tra
if ( !preg_match('/^[a-z0-9\_\-][a-z0-9\_\-\. ]*$/i', $filename) )
        || !is_file($upload_dir.$filename) || !is_readable($upload_dir.$filename) ) {
    echo "Loi: Ten file khong hop le hoac file khong ton tai!";
    exit(-1);
} //end if
 
//mở file để đọc với chế độ nhị phân (binary)
$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 ý rằng ta không cần kiểm tra tên file rỗng nữa vì ở trên ta đã kiểm tra ký tự đầu tiên của tên file, nên nếu tên file lã rỗng thì sẽ không có ký tự đầu tiên, do vậy điều kiện kiểm tra của hàm preg_match sẽ bị sai rồi.

THẮC MẮC NHỎ CUỐI CÙNG
Tới đây xem như chương trình của chúng ta xem như là đã hoàn chỉnh. Tuy nhiên, có thể bạn sẽ còn một thắc mắc nho nhỏ: ngoài kiểu dữ liệu application/octet-stream thì còn kiểu dữ liệu nào khác không? và mặc định thì PHP sẽ dùng kiểu dữ liệu gì để trả về cho browser?

Mặc định PHP sẽ trả về dữ liệu kiểu text/html cho browser. Một số kiểu dữ liệu tương ứng với các kiểu file thông dụng:

.GIF: image/gif
.JPG: image/jpeg
.PNG: image/png
.WAV: audio/wav
.MP3: audio/mpeg3
.DOC: application/msword
.PDF: application/pdf


Tuỳ vào kiểu của dữ liệu trả về mà browser có thể sẽ có những cách ứng khác nhau. Ví dụ nếu dữ liệu trả về là file ảnh thì browser sẽ hiển thị luôn, nếu là file nhạc thì browser sẽ gọi WMP lên để play, nếu là file PDF thì chương trình Acrobat sẽ được gọi...
Kiểu application/octet-stream để chỉ dữ liệu nhị phân (binary) chung chung. Nếu bạn chỉ muốn browser download và save file thì bạn chỉ cần trả về kiểu dữ liệu application/octet-stream là đủ.
Vậy thì nảy sinh 1 vấn đề nữa: tìm danh sách các kiểu dữ liệu tương ứng với từng loại file ở đâu? Google là trợ thủ đắc lực của bạn vui Hoặc bạn có thể xem mục "CÁC TÀI LIỆU THAM KHẢO" ở cuối bài viết.

VÀI LỜI NGỎ TRƯỚC KHI KẾT THÚC
Sau khi đọc hết bài viết, chắc bạn cũng thấy rằng việc viết 1 chương trình quản lý download file cho website cũng không phải là quá phức tạp. Cũng như tiêu đề của bài viết đã nói "Viết một chương trình download manager đơn giản", chương trình của chúng ta khá đơn giản nhưng cũng có đủ các chức năng cơ bản cần thiết. Các chức năng "tiền download" hoặc "hậu download" bạn có thể dễ dàng tự phát triển thêm tuỳ vào nhu cầu của bạn, ví dụ như tăng biến đếm số lần download của file, kiểm tra login trước khi cho download. Bạn chỉ cần chú ý một số điểm sau khi viết 1 chương trình download manager:

- Bạn nên để các file upload lên trong 1 thư mục riêng để dễ bề quản lý. Tốt nhất là để trong 1 thư mục không thể truy cập trực tiếp được từ Web mà chỉ có thể đọc bởi chương trình PHP của bạn.
- Kiểm tra kỹ tên file được người dùng nhập vào.
- Mở file để đọc ở chế độ nhị phân (binary). Bạn tham khảo thêm các tham số của hàm fread trong PHP.
- Trả về kiểu dữ liệu của file và các thông số cần thiết khác qua lệnh header().
- Nếu không thật sự cần thiết thì nên để đường dẫn download trực tiếp thay vì dùng download manager, vì như vậy sẽ download nhanh hơn và server ít phải xử lý thêm nhiều công việc.

Chúc bạn thành công!

TÀI LIỆU THAM KHẢO
- PHP Manual:  *http://www.php.net/manual/en/index.php
- Lệnh fpassthru:  *http://www.php.net/manual/en/function.fpassthru.php
- Lệnh fopen:  *http://www.php.net/manual/en/function.fopen.php
- Lệnh preg_match:  *http://www.php.net/manual/en/function.preg-match.php
- Và Regular Expression trong PHP:  *http://www.php.net/manual/en/ref.pcre.php
- Google: từ khoá MIME types list
- Các kiểu dữ liệu tương ứng với các kiểu file thông dụng:  *http://www.webmaster-toolkit.com/mime-types.shtml

Nguồn: Diễn đàn Tin học
↑↑ Lượt xem: 213
score
Đánh giá: 4.5/ 5, 213 bình chọn
- Chia sẻ:G  T
BBCode:

Link:
+ Còn “nhiều” Lắm!
+

Share code Diễn đàn trên Xtgem Full chức năng cực chất GetSmile.Mobie.In bởi Cú Đêm Việt Nam

+

Share code PHP hiển thị thông tin khách đang online trên Site

+

Sử dụng HTML và CSS tạo hiệu ứng hiển thị mô tả khi di chuột vào hình ảnh

+

Ajax là gì? Hướng dẫn code cơ bản khi xử lý dữ liệu với jQuery Ajax

+

Share full code PHP bộ tool cài đặt và quản lý Filelist KhoTruyen365 Xtgem

Trang chủ Cú Đêm Việt Nam Trang Chủ[1-1-213]