Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как отдать файл из скрипта 
:(
    Опции темы
Kiber_rat
Дата 4.12.2005, 03:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: 1
Всего: 9



Вопрос следующий. У меня есть CGI-ка которой в качастве параметра передается некий ключ, в ответ она должна отдать пользователю файл (архив к примеру). Т.е. после того как я обращаюсь к http://sample_site.net/download.cgi?key=qwe у меня появляется окошко с предложением записать файл. Вариант с редиректом меня не устраивает, поскольку раскрывает расположение файла на сервере и потом его можно будет скачать без обращения к скрипту. Есть вариант передать заголовок с Content-Type application/x-download и потом просто вывести файл, но тут возникает проблема с тем, как передать имя файла. У кого есть идеи?


--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
korob2001
Дата 4.12.2005, 08:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



Попробуй открыть файл, читать скажем по 1024 байта и выводить в STDOUT, т.е. что-то типа этого.
Код

# Здесь заголовок
open( F, "< files/myfile.zip" ) or die $!;
binmode STDOUT;
print STDOUT $buff while read( F, $buff, 1024 );
close(F);

Хотя точно не уверен, что это поможет. Но по идее должно сработать под никсами, если установить права 0644 на этот файл.

Второй способ, уже наверняка:

0. Создаём блокировку на отдельный файл.
1. Программа получает ключь в качестве параметра.
2. Открывает DBM с записями такого вида: key => faa5a88cff31f2445e.mp3, т.е. каждый файл связан с определённым ключём.
3. Получаем имя файла по ключу.
3. Полученный файл выдаём клиенту.
4. Генерируем новое имя.
5. Переименовуем файл.
6. Изменяем имя файла в DBM файле.
7. Закрываем DBM.
8. Снимаем блокировку.

PERL работает с DBM довольно быстро, переименовка файла производится тоже быстро, так что это не должно сильно затормозить твою программу. Юзер же будет получать старое имя, которое уже не является действительным. Если хочешь выдавать файл с одним и тем же, реальным, именем, то в том же DBM можно так же хранить и его. Например так должна выглядеть одна из записей в нашем DBM:
key => faa5a88cff31f2445e.mp3::real_file_name.mp3
Где real_file_name.mp3 это и есть реальное имя фала, которое будешь передавать в зоголовке. Так же в этом же DBM можно хранить и другую информацию о файле, например его размер и т.д.

Это сообщение отредактировал(а) korob2001 - 4.12.2005, 08:38


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Kiber_rat
Дата 4.12.2005, 08:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: 1
Всего: 9



То что ты посоветовал у меня уже сделано smile Файл сопоставляется по ключу, и отдается блоками юзеру, с этим проблем нет. Проблема в том, что имя, под которым юзеру предлагается сохранить файл, это имя скрипта к которому он обращается. А мне нужно что бы у него предлагалось то имя, которое мне надо. Т.е. что бы скачать файл qwe.avi нужно обратиться к URL http://samplesite.net/qwe.avi, а если обратиться к http://samplesite.net/download.cgi?key=qwe то браузер предложит записать файл как download.download (если Content-Type application = x-download). Попробуй сам... Есть еще параметр Content-Dispisition в котором теоретически можно передать имя, но это работает не всегда и не во всех браузерах.


--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
korob2001
Дата 4.12.2005, 08:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



Попробуй таким образом указать заголовок:
Код

print "Cache-control: no-cache\n";
print "Content-Length: $size \n";
print "Content-Disposition: filename=$file \n";
print "Content-type:  application/force-download\n\n";



--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Kiber_rat
Дата 4.12.2005, 09:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: 1
Всего: 9



Пробовал... IE через раз понимает, Opera и Firefox ни разу, wget - тоже не понимает...


--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
korob2001
Дата 4.12.2005, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



Так ты под все браузеры и не подстроишься, они вообще как хотят так и парсят заголовки. Это вечная проблема.
Воспользуйся вторым способом и вместо того, что бы читать файл побайтно, делай на него редирект. Так как имя файла будет каждый раз меняться, то юзеру, единственным способом добраться до файла, будет твоя программа, так как именно она может узнать временное имя файла на сервере.

Это сообщение отредактировал(а) korob2001 - 4.12.2005, 09:34


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Kiber_rat
Дата 4.12.2005, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: 1
Всего: 9



К сожалению (или к счастью) но политика в нашей мастерской такая, что наши сайты должны работать корректно ПОД ЛЮБЫМ браузером из известных, т.е. как минимум это IE(5.5,6...), Opera, FireFox, Netscape. Таким образом отпадает вопрос в том что "не подстроишься", партия сказала "Надо!" - комсомол ответил "Есть!" smile
Далее, что касается изменения имени файла на диске. По некоторым соображениям меня это не устраивает. Кроме того, это не решает ту проблему о которой я собственно и говорю. Файл все равно будет отдаваться не с тем именем которое мне нужно. В принципе есть вариант, который может работать со всеми броузерами. Имя файла для отдачи браузерами берется из самого URL на тот случай, если в заголовках его не будет(вероятно). Таким образом, надо сделать так, что-бы песледним элементом пути в запрашиваевом URL был нужный нам файл, что-то такое:
http://samplesite.net/qwe.avi?key=qwe Осталось только отделить зерна от плевел и все получится. Тут нам может помочь .htaccess, есть у него такая опция:
Код
Action myaction /cgi-bin/download.cgi
AddHandler myaction *.avi
Т.е. при обращении к файлам с расширением avi у нас вызыватеся скрипт, который отделяет имя файла и переданный параметр, а потом передает это cgi-ке, которая и отдает файл. Что-то в этом роде.

Это сообщение отредактировал(а) Kiber_rat - 4.12.2005, 10:57


--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
korob2001
Дата 4.12.2005, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



Цитата

К сожалению (или к счастью) но политика в нашей мастерской такая, что наши сайты должны работать корректно ПОД ЛЮБЫМ браузером из известных, т.е. как минимум это IE(5.5,6...), Opera, FireFox, Netscape. Таким образом отпадает вопрос в том что "не подстроишься", партия сказала "Надо!" - комсомол ответил "Есть!"

smile Ну это нормальная политика, для всех WEB разработчиков. Только в данный момент речь идёт не о теле документа, а о его заголовке. Если ты файл не будешь переименовывать, то его имя можно будет запросто узнать воспользовавшись таким софтом как например: ReGet Deluxe.

Это сообщение отредактировал(а) korob2001 - 4.12.2005, 11:37


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Kiber_rat
  Дата 4.12.2005, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: 1
Всего: 9



Ты что-то упустил, для меня не важно узнает юзер имя файла или нет, важно
Цитата
расположение файла на сервере и потом его можно будет скачать без обращения к скрипту

Кой чего получилось. smile
Вот код:
Код
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw(:standard);
my $right_key='qqwwee';
my %Q=CGI::Vars();
my $file = do{$ENV{PATH_INFO}=~m#^.*/([^/\?]+).*$#;$1};
unless (-e "$file" and $Q{key} eq $right_key) {
    print header();
    print '<center><font color=red>Error, file not exists or wrong key!';
    exit;
}   
open my $fh, "<$file" or die "$!\n";
my $buf=0;
$|=1;
print header(
    -type=>'application/force-download', 
    -disposition=>"attachment, filename=$file",
);
print $buf while read($fh, $buf,1024);
exit;

Скрипт кладем в папку files (вместе с файлами для скачивания) и туда же кладем такой .htaccess
Код
Action qwe /files/test.cgi
    AddHandler qwe .avi
    AddHandler qwe .wmv
    AddHandler qwe .mov
Options +ExecCGI

Запрашиваем файл так: http://samplesite.net/files/file.avi?key=qqwwee

Это сообщение отредактировал(а) Kiber_rat - 4.12.2005, 12:19


--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
sharq
Дата 5.12.2005, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Perl Liker
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 13.12.2004
Где: Ростов-на-Дону

Репутация: 2
Всего: 28



Kiber_rat то, что ты хочешь сделать, называется системой антилича. (by the way smile )


Цитата(Kiber_rat @ 4.12.2005, 13:13)
Скрипт кладем в папку files (вместе с файлами для скачивания) и туда же кладем такой .htaccess
Код
Action qwe /files/test.cgi
    AddHandler qwe .avi
    AddHandler qwe .wmv
    AddHandler qwe .mov
Options +ExecCGI

Запрашиваем файл так: http://samplesite.net/files/file.avi?key=qqwwee

К сожалению, но так не корректно! Для этих целей есть mod_rewite.
Код

RewriteEngine On
RewriteRule ^files/(.*)\.avi cgi-bin/script.pl [L,QSA]


Это самый примитивный пример, плюс: читаем параграф Артемия Лебедева о чистоте url.

И все-таки ссылку для скачивания лучше сделать через сессии, например, такой:
Цитата
http://samplesite.net/files/faa5a88cff31f2445e88cff31f2445e/real.file

А сам файл реально может находиться где угодно.

smile


--------------------
[color=gray]There's More Than One Way To Do It[/color]
PM MAIL WWW ICQ Skype   Вверх
Kiber_rat
Дата 5.12.2005, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: 1
Всего: 9



Честно говоря, я не уверен, что то, что мне надо, это "система антилича", есть схожие требования и все. Далее
Цитата
http://samplesite.net/files/faa5a88cff31f2445e88cff31f2445e/real.file
- это удобочитаемый URL? (это к статье Лебедева)
Далее, что касается сессий. Если я ничего не путаю, сессии предназначены для того, что бы хранить данные связанные с определенныи пользователем, ну или что-то в этом роде. У меня человек получает письмо с URL по которому он может скачать файл, с сайта, на котором кроме возможности скачать с него файл (по уникальному ключу) больше ничего нет и быть не должно... Сессии?
Цитата
К сожалению, но так не корректно! Для этих целей есть mod_rewite.
- можно несколько более развернутый ответ? Как именно мне поможет mod_rewite в приложении к моей задаче. И последнее, что именно некорректно в моем коде? То что после имени файла идет передаваемый параметр? Так это не противоречит RFC, болеетого, я не уверен что это противоречит чему-то из того, о чем писал Лебедев...


--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
sharq
Дата 5.12.2005, 19:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Perl Liker
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 13.12.2004
Где: Ростов-на-Дону

Репутация: 2
Всего: 28



Kiber_rat
Цитата(Kiber_rat @ 5.12.2005, 19:42)
Честно говоря, я не уверен, что то, что мне надо, это "система антилича", есть схожие требования и все.

smile

Цитата(Kiber_rat @ 5.12.2005, 19:42)
Цитата
http://samplesite.net/files/faa5a88cff31f2...2445e/real.file
- это удобочитаемый URL? (это к статье Лебедева)

Отличная ссылка на скачку, один раз скачал и забыл. smile
На самом деле, в url следует избегать ипользовать символы ?, &, = и др., об этом и велась речь в статье и именно это я тебе написал.

Цитата(Kiber_rat @ 4.12.2005, 04:38)
поскольку раскрывает расположение файла на сервере и потом его можно будет скачать без обращения к скрипту

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

Цитата(Kiber_rat @ 5.12.2005, 19:42)
Если я ничего не путаю, сессии предназначены для того, что бы хранить данные связанные с определенныи пользователем, ну или что-то в этом роде

и для этого тоже.

Можешь поискать решения антилича и посмотреть как там работают ссылки на скачку.


Цитата(Kiber_rat @ 5.12.2005, 19:42)
Как именно мне поможет mod_rewite в приложении к моей задаче.


Цитата(sharq @ 5.12.2005, 18:54)
Для этих целей есть mod_rewite.

RewriteEngine On
RewriteRule ^files/(.*)\.avi cgi-bin/script.pl [L,QSA]


Цитата(Kiber_rat @ 5.12.2005, 19:42)
что именно некорректно в моем коде

Решение подобной задачи. smile Просто посмотри mod_rewrite и пойми о чем я тебе говорю.

Если тебе не нравится предложенный вариант решения, то забудь. smile
Хотя по-моему это лучше.

smile


--------------------
[color=gray]There's More Than One Way To Do It[/color]
PM MAIL WWW ICQ Skype   Вверх
Kiber_rat
Дата 6.12.2005, 02:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: 1
Всего: 9



Все таки не пойму как мне использовать сессии. Приведи пример плз. Еще раз объясню задачу. Юзер получает письмо в котором лежит URL по которому он может скачать некий файл. Вместе с URL надо предать некий код, который позволит однозначно идентифицировать этого юзера (к примеру запомнить что юзер с таким кодом заходил с такого-то IP, столько то раз). То есть, до того как юзер зайдет скачивать файл, он на сервере ни разу не был. Ты можешь рабочий пример написать?
smile


--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: CGI программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к CGI программированию
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", качать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: разработка для Web | Следующая тема »


 




[ Время генерации скрипта: 0.0981 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.