Четверг, 2025-01-23, 9:00 AM
Статьи - PHP
Приветствую Вас Гость | RSS
Главная страница Каталог статей Регистрация Вход
Меню сайта

Категории каталога
PHP [158]
Статьи по PHP

Наш опрос
Какую технологию вы предпочитаете?
Всего ответов: 250

Начало » Статьи » PHP » PHP

PHP: Скачивание файлов с докачкой
Многие интернет-проекты (неважно, что это: движки форумов, фотогалереи или что-то ещё) позволяют пользователям загружать файлы на сайт и скачивать их оттуда.

С закачкой проблем не возникает никогда.

А вот со скачиванием закачанных файлов зачастую бывает одна маленькая проблема: многие вебмастера хотят знать, сколько раз был скачан тот или иной файл. Что же они делают? Очень просто: дают ссылку не на собственно файл, а на некоторый скрипт, который выглядит примерно так:

<?php // тут подсчёт скачиваний, разные действия // а дальше: просто выдача всего содержимого файла, примерно так: readfile ($filename);?>
И всё бы ничего, но:

Файлы порой бывают очень большими,
а связь — очень некачественной.
Ну и что? А очень просто: выданный таким образом файл нельзя скачивать порциями. То есть ни один менеджер скачиваний (например, ReGet, FlashGet или Download Master и прочие) не смогут:

Скачивать файл в несколько потоков;
Приостановить скачивание в любой момент, а через некоторый промежуток времени начать скачивать файл с места остановки (а ведь в этом и суть докачки).
Что делать?

Вот и меня посетила такая мысль. Полчаса экспериментов — и у меня получилась очень хорошая функция. Отдаю её Вам:

function downloadFile($filename, $mimetype='application/octet-stream') { if (!file_exists($filename)) die('Файл не найден'); $from=$to=0; $cr=NULL; if (isset($_SERVER['HTTP_RANGE'])) { $range=substr($_SERVER['HTTP_RANGE'], strpos($_SERVER['HTTP_RANGE'], '=')+1); $from=strtok($range, '-'); $to=strtok('/'); if ($to>0) $to++; if ($to) $to-=$from; header('HTTP/1.1 206 Partial Content'); $cr='Content-Range: bytes ' . $from . '-' . (($to)?($to . '/' . $to+1):filesize($filename)); } else header('HTTP/1.1 200 Ok'); $etag=md5($filename); $etag=substr($etag, 0, 8) . '-' . substr($etag, 8, 7) . '-' . substr($etag, 15, 8); header('ETag: "' . $etag . '"'); header('Accept-Ranges: bytes'); header('Content-Length: ' . (filesize($filename)-$to+$from)); if ($cr) header($cr); header('Connection: close'); header('Content-Type: ' . $mimetype); header('Last-Modified: ' . gmdate('r', filemtime($filename))); $f=fopen($filename, 'r'); header('Content-Disposition: attachment; filename="' . basename($filename) . '";'); if ($from) fseek($f, $from, SEEK_SET); if (!isset($to) or empty($to)) { $size=filesize($filename)-$from; } else { $size=$to; } $downloaded=0; while(!feof($f) and !connection_status() and ($downloaded<$size)) { echo fread($f, 512000); $downloaded+=512000; flush(); } fclose($f);}
Функция принимает два параметра: $filename — полный путь до файла, $mimetype — MIME-тип файла (если не знаете, что это такое — не указывайте второй параметр при вызове функции).

Вызов функции может быть например таким:

downloadFile('file/archive.zip', 'application/zip'); // Выдаём пользователю файл "file/archive.zip" и указываем MIME-тип
Или таким:

downloadFile('i_want_to_break_free.mp3', 'audio/mpeg'); // Выдаём файл "i_want_to_break_free.mp3" и снова указываем MIME-тип
А можно и вот так:

downloadFile('somefile.ext'); // Здесь пользователю отдаётся файл "somefile.ext", но MIME-тип не указывается. // Впрочем, ничего страшного в этом нет.
Однако не забудьте вот о чём: функция посылает заголовки header. Значит до вызова функции не должен выводиться никакой текст.

После вызова функции лучше тоже ничего не выводить — некоторые менеджеры закачек не смотрят на то, что необходимые размеры скачаны и качают пока не закончится поток данных. А это приведёт к тому, что в нормальный файл попадёт всякий бред.

Я бы посоветовал сразу после вызова downloadFile() сделать вызов die();

Глупо было бы думать, что я один такой умный (хотя и хотелось бы) . Но Вы можете (вместо моей функции) использовать PEAR-библиотеку HTTP_Download, которая реализует всё то, что и моя функция, и много других возможностей (как-то: кэширование, сжатие данных «на лету» и прочее).

Категория: PHP | Добавил: webmaster (2006-12-02)
Просмотров: 344 | Рейтинг: 0.0 |

Всего комментариев: 0
Имя *:
Email *:
Код *:
Форма входа

Сервисы

Поиск по каталогу

Друзья сайта

| Ссылки 1 | Ссылки 2 | Ссылки 3 |
www.webmaster.clan.su Каталог+поисковая система be number one Bakililar.az Top Sites Сервис авто регистрации в
каталогах, статьи про раскрутку сайтов, web дизайн, flash, 
photoshop, хостинг, рассылки; форум, баннерная сеть, каталог 
сайтов, услуги продвижения и рекламы сайтов Скрипт для определения тиц (Яндекс CY: индекс цитирования). Определение pr (Google Pagerank). Проверить тиц pr сайта.
Copyright WebMaster.Clan © 2006 Бесплатный хостинг uCoz