PHP đọc ghi tệp để lưu nhật ký, xuất CSV, đọc cấu hình, và nhận tệp người dùng tải lên (ảnh đại diện, bài nộp). Bài này học các hàm tệp, thư mục, CSV/JSON và quy trình upload an toàn.
- Đọc, ghi, nối tệp văn bản
- Làm việc với thư mục và CSV, JSON
- Nhận tệp upload qua $_FILES
- Kiểm tra kích thước, loại tệp, đổi tên và lưu an toàn
- Handle
- Con trỏ tệp trả về bởi fopen.
- $_FILES
- Mảng chứa thông tin tệp tải lên.
- MIME type
- Loại nội dung tệp: image/jpeg, application/pdf.
- tmp_name
- Đường dẫn tệp tạm máy chủ lưu trước khi bạn di chuyển.
Khái niệm và lý thuyết
Hai cách làm việc với tệp: hàm nhanh file_get_contents/file_put_contents cho tệp nhỏ, và bộ fopen/fgets/fwrite/fclose khi đọc từng dòng hoặc tệp lớn. Upload: trình duyệt gửi tệp bằng form multipart/form-data; PHP lưu vào thư mục tạm và báo qua $_FILES; mã của bạn phải kiểm tra rồi move_uploaded_file về thư mục đích. Thư mục đích cần quyền ghi và không được cho phép chạy PHP.
Đọc ghi tệp
<?php
$tep = __DIR__ . "/data/nhat_ky.txt";
file_put_contents($tep, date("c") . " Truy cập trang chủ\n", FILE_APPEND | LOCK_EX);
echo nl2br(htmlspecialchars(file_get_contents($tep)));
$dong = file($tep, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); // mảng từng dòng
echo count($dong), " dòng";
// Đọc từng dòng tệp lớn
$h = fopen($tep, "r");
while (($d = fgets($h)) !== false) { /* xử lý */ }
fclose($h);
var_dump(file_exists($tep), filesize($tep), is_writable(__DIR__ . "/data"));
unlink($tep); // xóa tệpThư mục, CSV, JSON
<?php
if (!is_dir("data")) mkdir("data", 0755, true);
foreach (scandir("data") as $f) if ($f[0] !== ".") echo $f, "<br>";
foreach (glob("uploads/*.jpg") as $anh) echo basename($anh), " ", pathinfo($anh, PATHINFO_EXTENSION), "<br>";
// Ghi và đọc CSV (mở được bằng Excel)
$ds = [["SV001", "Lò Văn An", 8.5], ["SV002", "Cầm Thị Bình", 6]];
$f = fopen("data/diem.csv", "w");
fwrite($f, "\xEF\xBB\xBF"); // BOM để Excel hiện tiếng Việt
fputcsv($f, ["Mã", "Họ tên", "Điểm"]);
foreach ($ds as $r) fputcsv($f, $r);
fclose($f);
$f = fopen("data/diem.csv", "r"); fgetcsv($f); // bỏ dòng tiêu đề
while (($r = fgetcsv($f)) !== false) echo implode(" | ", $r), "<br>";
fclose($f);
// JSON làm "CSDL mini"
file_put_contents("data/cau_hinh.json", json_encode(["theme" => "sang"], JSON_PRETTY_PRINT));
$ch = json_decode(file_get_contents("data/cau_hinh.json"), true);Upload tệp an toàn
<form method="post" enctype="multipart/form-data">
<input type="file" name="anh" accept="image/*" required>
<button>Tải lên</button>
</form>
<?php
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_FILES["anh"])) {
$f = $_FILES["anh"];
$loi = match ($f["error"]) {
UPLOAD_ERR_OK => null,
UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE => "Tệp quá lớn",
UPLOAD_ERR_NO_FILE => "Chưa chọn tệp",
default => "Lỗi tải lên ($f[error])",
};
if (!$loi && $f["size"] > 2 * 1024 * 1024) $loi = "Tối đa 2 MB";
$cho_phep = ["image/jpeg" => "jpg", "image/png" => "png", "image/webp" => "webp"];
$mime = $loi ? null : mime_content_type($f["tmp_name"]); // kiểm tra nội dung thật, không tin $f["type"]
if (!$loi && !isset($cho_phep[$mime])) $loi = "Chỉ nhận ảnh JPG, PNG, WebP";
if (!$loi) {
$ten_moi = bin2hex(random_bytes(8)) . "." . $cho_phep[$mime]; // đổi tên, bỏ tên gốc
$dich = __DIR__ . "/uploads/" . $ten_moi;
if (move_uploaded_file($f["tmp_name"], $dich)) {
echo "<img src='uploads/$ten_moi' width='200'>";
// lưu $ten_moi vào CSDL
} else $loi = "Không lưu được tệp";
}
if ($loi) echo "<p style='color:red'>$loi</p>";
}| Khóa $_FILES["anh"] | Ý nghĩa |
|---|---|
| name | Tên gốc (không tin cậy) |
| type | MIME do trình duyệt báo (không tin cậy) |
| tmp_name | Đường dẫn tạm |
| error | Mã lỗi, 0 là thành công |
| size | Kích thước byte |
Giới hạn upload trong php.ini: upload_max_filesize và post_max_size (mặc định 2M/8M). Upload nhiều tệp: name="anh[]" multiple, $_FILES["anh"]["name"] là mảng.
Không bao giờ dùng tên tệp gốc để lưu (có thể là ../../config.php hay virus.php). Luôn đổi tên, kiểm tra MIME thật và đặt .htaccess chặn chạy PHP trong thư mục uploads: php_flag engine off.
- Ghi nhật ký mỗi lượt truy cập (thời gian, IP, trang) vào tệp log.
- Xuất danh sách sinh viên ra CSV mở được bằng Excel có tiếng Việt.
- Làm form đổi ảnh đại diện: giới hạn 1 MB, chỉ JPG/PNG, hiển thị sau khi tải.
- Cho phép nộp bài PDF/DOCX, lưu tên tệp mới và tên gốc vào tệp JSON.
- file_get/put_contents cho tệp nhỏ; fopen/fgets cho tệp lớn.
- fputcsv/fgetcsv, json_encode/decode cho dữ liệu có cấu trúc.
- Upload: kiểm tra error, size, MIME thật, đổi tên, move_uploaded_file.
- Thư mục uploads: có quyền ghi, chặn chạy PHP.