PHP - Загрузка файла

Здравствуйте,野心勃勃的PHP开发者们!今天,我们将深入一个激动人心的话题,这将使您的网站增加一些很酷的功能 - 使用PHP下载文件。作为您友好的邻居电脑老师,我将引导您一步一步地完成这个旅程。所以,拿起你最喜欢的饮料,舒服地坐下,让我们开始编码吧!

PHP - Download File

Функция readfile()

В сердце загрузки файлов в PHP лежит функция readfile(). Эта полезная функция - ваш лучший инструмент, когда вы хотите прочитать файл и вывести его содержимое в буфер вывода. Не волнуйтесь, если это звучит немного технически - мы разберем это вместе!

Основное использование

Давайте начнем с простого примера:

<?php
readfile("example.txt");
?>

В этом фрагменте кода readfile() читает содержимое "example.txt" и выводит его напрямую в браузер. Это как магия - содержимое файла появляется на вашем экране!

Загрузка файлов

Теперь, где это становится интересным. Мы можем использовать readfile() для prompting下载文件. Давайте посмотрим на более полный пример:

<?php
$file = "myfile.pdf";

if(file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>

Ух, это много информации! Давайте разберем это:

  1. Мы указываем файл, который хотим下载 ($file = "myfile.pdf").
  2. Мы проверяем, существует ли файл, используя file_exists().
  3. Если да, то устанавливаем серию заголовков:
  • Content-Description говорит браузеру, что это передача файла.
  • Content-Type устанавливает MIME-тип в通用 двоичный файл.
  • Content-Disposition побуждает браузер下载 файл.
  • Другие заголовки обеспечивают то, что файл не кэшируется и обрабатывается правильно.
  1. Наконец, мы используем readfile() для вывода содержимого файла.

Распространенные типы файлов

Разные типы файлов могут требовать разные заголовки. Вот удобная таблица распространенных типов файлов и соответствующих заголовков Content-Type:

Тип файла Заголовок Content-Type
PDF application/pdf
ZIP application/zip
JPEG image/jpeg
PNG image/png
MP3 audio/mpeg
MP4 video/mp4

Создание ссылки для загрузки

Теперь, когда мы знаем, как инициировать下载, давайте создадим удобную ссылку для下载:

<!DOCTYPE html>
<html>
<body>

<h2>Загрузка файлов</h2>
<p><a href="download.php?file=myfile.pdf">Скачать PDF</a></p>

</body>
</html>

В этом HTML мы создаем ссылку на PHP-скрипт (download.php), который будет обрабатывать下载 файла. Мы передаем имя файла в URL в качестве параметра.

Теперь создадим скрипт download.php:

<?php
if(isset($_GET['file'])) {
$file = $_GET['file'];
$filepath = "uploads/" . $file;

if(file_exists($filepath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
readfile($filepath);
exit;
} else {
echo "Файл не найден.";
}
}
?>

Этот скрипт делает следующее:

  1. Проверяет, был ли передан параметр файла в URL.
  2. Конструирует полный путь к файлу (предполагая, что файлы находятся в каталоге "uploads").
  3. Если файл существует, устанавливает заголовки и инициирует下载.
  4. Если файл не существует, отображает сообщение об ошибке.

Учетные данные безопасности

Теперь я знаю, о чем вы думаете - "Но учитель, это не немного рискованно? Что, если кто-то попытается下载 файлы, которые он не должен?" Great вопрос! Вы absolutely правы, и это почему мы должны говорить о безопасности.

Валидация путей к файлам

Мы nunca должны доверять вводу пользователя напрямую. Вот улучшенная версия нашего скрипта для下载:

<?php
if(isset($_GET['file'])) {
$file = basename($_GET['file']);
$filepath = "uploads/" . $file;

// Валидация пути к файлу
$realPath = realpath($filepath);
$uploadDir = realpath("uploads/");

if($realPath === false || strpos($realPath, $uploadDir) !== 0) {
die("Некорректный путь к файлу.");
}

if(file_exists($filepath)) {
// ... (остаток кода для下载)
} else {
echo "Файл не найден.";
}
}
?>

В этой версии:

  1. Мы используем basename() для удаления попыток обхода каталогов.
  2. Мы используем realpath() для получения реального пути к файлу и каталогу загрузки.
  3. Мы проверяем, начинается ли реальный путь файла с пути к каталогу загрузки, чтобы мы не могли получить доступ к файлам за пределами intended каталога.

Заключение

И вот мы добрались до этого,folks! Мы прошли через страну下载 файлов PHP, от basics readfile() до создания ссылок для下载 и даже коснулись важных вопросов безопасности. Помните, с великой силой приходит великая ответственность - всегда validate ввод пользователя и думайте о безопасности при работе с下载ами файлов.

Надеюсь, вам понравился этот урок так же, как и мне было приятно его преподаать. Continue practicing, continue coding, и вы узнаете, как создавать удивительные PHP-приложения с различными cool функциями для下载. До свидания, счастливого кодирования!

Credits: Image by storyset