Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Скачка файлов... Разовые ссылки...
 
 автор: Aid   (16.05.2007 в 10:09)   письмо автору
 
 

Доброго времени суток. Вот, пришёл к ВАМ с очередной проблемой, с которой столкнулся только что... Сделать необходимо следующее: "Есть на сервере файлы, которые можно скачать, но доступ к самим файлам (исходным) ограничен (сам файл называться может, ну, допустим, ммм, по id, согласно id в таблице БД)... Т.е. пользователю должен выдаваться с нормальным именем... (Надеюсь меня поймут :) )". Так сказать должна быть разовая ссылка В общем сделать то такое нетрудно:

<?php

header
('Content-type: application/pdf');

header('Content-Length: ' filesize("original.pdf"));

header('Content-Disposition: attachment; filename="downloaded.pdf"');

readfile('original.pdf');

?>

, но тогда создаётся проблема с докачкой.
Или же просто-напросто копировать файлы в папки с неопределённым названием (т.е. хэш-код какой-нить). И удалять их через сутки (или меньше)...

   
 
 автор: golovdinov   (16.05.2007 в 14:56)   письмо автору
 
   для: Aid   (16.05.2007 в 10:09)
 

Хеши можно хранить в БД, а при обращении к файлу например по ссылке ?id=23&code=ekfjwhfc784fj7tnw93rfhw48 проверять соответствие хеша и ip, ну и конечно через некоторое время удалять запись с хешем из БД.

   
 
 автор: Aid   (17.05.2007 в 12:46)   письмо автору
 
   для: golovdinov   (16.05.2007 в 14:56)
 

Не, не то... Надо, чтоб пользователи не знали настоящего имени файла... Да, я конечно понимаю, что хэши необходимо хранить в БД, там же и дату создания ссылки... Но вопрос остаётся тот же... Как сделать так, чтоб пользователь не знал настоящего имени файла (т.е. не знал, откуда его можно скачать), но при этом, чтоб мог его закачивать и докачивать :)

   
 
 автор: Loki   (16.05.2007 в 15:37)   письмо автору
 
   для: Aid   (16.05.2007 в 10:09)
 

Если у вас здоровые файлы и большая посещаемость, то этих временных файлов быстро накопится изрядное количество. Но если это не так, то я бы не стал отдавать файл через скрипт.

Если у вас юниксовый сервер, то можно использовать ссылки на файлы - их-то можно плодить без счета:)

   
 
 автор: Trianon   (16.05.2007 в 15:57)   письмо автору
 
   для: Aid   (16.05.2007 в 10:09)
 

Проблема с докачкой решается генерацией поля заголовка Accept-Ranges: в откликах, обработкой полей Range: в http-запросе и применением связки fopen, fseek,fpassthru вместо readfile

   
 
 автор: Aid   (17.05.2007 в 12:35)   письмо автору
 
   для: Trianon   (16.05.2007 в 15:57)
 

Да, конечно интересно, но есть небольшое "но"... Клиент при этом должен указать что-либо (может позицию курсора, в файле)? Я пытался посмотреть и GET и POST, но там глухо, как в танке... пусто, клиент ничего не передаёт... Мож подскажешь тогда, как узнать куда fseek'oм переходить?

   
 
 автор: Trianon   (17.05.2007 в 12:44)   письмо автору
 
   для: Aid   (17.05.2007 в 12:35)
 

print_r(getallheaders());
$_SERVER тоже имеет смысл смотреть.

   
 
 автор: Aid   (17.05.2007 в 13:14)   письмо автору
 
   для: Trianon   (17.05.2007 в 12:44)
 

СПАСИБО!!!
Знаешь, я и не думал, что там всё так просто... Хотя это пока что только Mozilla была при проверке (т.е. FireFox), но докачивает без fseek... Посмотрим на остальные...
и ещё раз СПАСИБО!!!

   
 
 автор: Trianon   (17.05.2007 в 13:16)   письмо автору
 
   для: Aid   (17.05.2007 в 13:14)
 

если у Вас не применяется fseek, значит где-то Вы облажались....

   
 
 автор: Aid   (17.05.2007 в 14:12)   письмо автору
 
   для: Trianon   (17.05.2007 в 13:16)
 

стоп... Вы используете $_SERVER['HTTP_RANGE'] ?

   
 
 автор: Trianon   (17.05.2007 в 14:20)   письмо автору
 
   для: Aid   (17.05.2007 в 14:12)
 

Откуда именно вытягивать конкретное поле заголовка запроса - не столь важно.
Можно из getallheaders(), можно из $_SERVER, можно из переменной окружения.
Суть от этого не меняется. fseek при обработке запроса диапазона всё равно необходим.

   
 
 автор: Aid   (17.05.2007 в 14:21)   письмо автору
 
   для: Trianon   (17.05.2007 в 14:20)
 


<?php

$tmp 
trim($_SERVER['HTTP_RANGE'], "-");
$wr intval(substr($tmp6));
$name "1.rar";
$fp fopen($name'rb');

header("Accept-Ranges: bytes");
header("Content-Type: application/rar");
header("Content-Length: " filesize($name));
fseek($fp$wr);
fpassthru($fp);

?>



Здесь что-то не так... А я что именно -- понять не могу...

   
 
 автор: Trianon   (17.05.2007 в 14:37)   письмо автору
 
   для: Aid   (17.05.2007 в 14:21)
 

кошмар.
Боже, какой кошмар.

$tmp = trim($_SERVER['HTTP_RANGE'], "-");

в этом поле указывается ПозицияНачала-ПозицияКонца
Позиция начала - это позиция первого байта, который нужно передать.
Позиция конца - это позиция последнего байта, который нужно передать.
причем и то и другое число может отсутствовать. Отсюда и минус сбоку.
Если отсутствует позиция начала - она равна нулю.
Если отсутствует позиция конца - она равна длине файла без единицы.
Исправляйте это $wr = intval(substr($tmp, 6));


header("Accept-Ranges: acceptable-ranges");
в этом поле никаких acceptable-ranges быть не должно.
Должно быть none , если Вы не умеете обрабатывать диапазонные запросы
либо должно быть bytes, если умеете.


header("Content-Type: application/rar");
header("Content-Length: " . filesize($name));
fseek($fp, $wr);
fpassthru($fp);


кроме того нужно выдавать статус 206 Partial Content и
поле заголовка отклика Content-Range

И вообще: http://zeus.sai.msu.ru:7000/nets/semenov/4/45/http4561.shtml
либо оригинальный RFC по HTTP/1.1... чтоб не соврать RFC-2616....
да. именно он.http://www.faqs.org/rfcs/rfc2616.html

   
 
 автор: Aid   (17.05.2007 в 15:18)   письмо автору
 
   для: Trianon   (17.05.2007 в 14:37)
 

По-моему мне пора вешаться... :)
Да уж, что-то я смотрю на это всё, как баран на новые ворота... Ну явно не моя тема... На С++ было гораздо проще с этим всем

   
 
 автор: Aid   (17.05.2007 в 15:20)   письмо автору
 
   для: Trianon   (17.05.2007 в 14:37)
 

как-то не могу сегодня, не взглянув хотя бы на кусочек кода (нормального)...

   
 
 автор: Aid   (21.05.2007 в 13:47)   письмо автору
 
   для: Trianon   (17.05.2007 в 14:37)
 

Уважаемый, Trianon, не могшли бы Вы дать кусочек кода?
А то, хоть убейте, понять принцип работы не могу... Т.е., не понимаю... Хоть бы глазком на такое взглянуть...

   
 
 автор: Trianon   (21.05.2007 в 14:43)   письмо автору
 
   для: Aid   (21.05.2007 в 13:47)
 

Честно скажу, написано только что, и на одном дыхании, так что корректность не проверял.
Но то, что вспомнил - учел.

<?php 

$handle 
fopen($fullname'rb');
fseek($handle0SEEK_END);
$size ftell($handle);

if(isset(
$_SERVER['HTTP_RANGE']))
{
    
$range explode('-'$_SERVER['HTTP_RANGE']);
    if(!
$range[0])$range[0] = 0;
    if(
$range[1]) ++ $range[1];
    else 
$range[1] = $size;
}
else 
$range = array(0$size);
if(
$range[0] < 0$range[0] = 0;
if(
$range[1] > $size$range[1] = $size;

$part_size $range[1]-$range[0];
$range_start $range[1];

if(
$range[0] > || $range[1] < $size)
{
    
$range_stop $range[1]-1;
    
header("206 HTTP/1.0 Partial content");
    
header("Content-Length: $part_size");
    
header("Content-Range: bytes $range_start-$range_stop/$size");
}else
    
header("Content-Length: $size");
header("Accept-Ranges: bytes");
header("Content-Type: application/octet-stream; name=\"$name\"");
header("Content-Disposition: attachment; filename=\"$name\"");

fseek($handle$range_startSEEK_SET);
if(
$arnge[1] == $size)
    
fpassthru($handle);
else
    for(
$blklen 16384$pos $range_start$pos $range[1]; $pos += $buflen)
    {
        if(
$range[1]-$pos $blklen)
            
$blklen intval($range[1]-$pos);
        
$buffer fread($handle$blklen);
        
$buflen strlen($buffer);
        echo 
$buffer;
    }
?>

   
 
 автор: tAleks   (12.06.2007 в 10:40)   письмо автору
 
   для: Trianon   (21.05.2007 в 14:43)
 

Trianon, не сочтите за труд, пожалуйста, прокоментируйте ваш пример, как для новичков.

   
 
 автор: Trianon   (12.06.2007 в 15:22)   письмо автору
 
   для: tAleks   (12.06.2007 в 10:40)
 

Пример расчитан на человека а) прочитавшего разделы 9.2.7, 13.5, 13.36 документа RFC-2616 или его перевода, и б) представляющего, что делают функции explode, ftell, fpassthru.

Кстати, пример, похоже, содержит ошибку.
Ненамеренно, конечно, так получилось.
В ближайшее время попытаюсь её исправить.

   
 
 автор: tAleks   (12.06.2007 в 19:12)   письмо автору
 
   для: Trianon   (12.06.2007 в 15:22)
 

>Пример расчитан на человека
> а) прочитавшего разделы 9.2.7, 13.5, 13.36 документа RFC-2616 или его перевода, и

Дайте пожалуйста ссылку на перевод.


> б) представляющего, что делают функции explode, ftell, fpassthru.

Знаю, только то, что написано о них в мануале.

>Кстати, пример, похоже, содержит ошибку.
>Ненамеренно, конечно, так получилось.
>В ближайшее время попытаюсь её исправить.

Жду. Надо позарез...

   
 
 автор: kasmanaft   (12.06.2007 в 19:21)   письмо автору
 
   для: tAleks   (12.06.2007 в 19:12)
 

> Дайте пожалуйста ссылку на перевод.
Вам ее уже не раз давали...
Есть и в этой теме, ~10 постов наверх.
("Гипертекстный протокол HTTP")

   
 
 автор: tAleks   (12.06.2007 в 19:31)   письмо автору
 
   для: kasmanaft   (12.06.2007 в 19:21)
 

"Гипертекстный протокол HTTP" и RFC-2616 это одно и то же?
Просто я думал что это разные вещи....

Если нет, тогда спасибо... два раза... :)

Седня целый день его читаю.... :) Голова уже квадратная... :)

   
 
 автор: -=|NickK|=-   (13.06.2007 в 15:50)
 
   для: Trianon   (21.05.2007 в 14:43)
 

На первый взгляд:
- Не совпадают имена переменных с именем файла
- очепятка: if($arnge[1] == $size)

   
 
 автор: -=|NickK|=-   (13.06.2007 в 15:57)
 
   для: Trianon   (21.05.2007 в 14:43)
 

Да, и еще чередование blklen / buflen )

   
 
 автор: Trianon   (13.06.2007 в 16:03)   письмо автору
 
   для: -=|NickK|=-   (13.06.2007 в 15:57)
 

очепятка - да.
Но не в ней суть.

Касательно blklen/buflen - тут всё чисто.
blklen - размер блока чтения.
buflen - размер прочтенного участка файла.

   
 
 автор: -=|NickK|=-   (13.06.2007 в 15:59)
 
   для: Trianon   (21.05.2007 в 14:43)
 

Чет туплю... Не дочитал до конца...

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования