div.main {margin-left: 20pt; margin-right: 20pt}
Загрузка файлов на сервер и посылка e-mail с
вложениями
Одним из популярнейших вопросов во всевозможных форумах является вопрос
«Как загрузить файл на сервер?». А ведь на самом деле это не так
сложно, как кажется на первый взгляд. И чтобы не было совсем легко – пусть
скрипт, который приведен ниже еще и посылает этот файл по почте, в виде
вложения.
Для использования скрипта нужно установить 2 модуля: MIME::Lite
и CGI
Второй скорее всего у вас есть, а первый необходимо скачать.
Приступим к разбору листинга:
Строчки с первой по третью не делают ничего очень важного. Первая –
стандартное начало любого скрипта, вторая и третья – по вкусу.
5-12 строки – конфигурация скрипта:
Cтроки 7,8,9 – параметры письма (соответственно от кого, к кому и тема)
Cтрока 10 – значение INCLUDE_META, которое если равно 1, то в письмо
включается еще одно вложение с различной служебной информацией: о
загруженном файле, переменных окружения и т.д.
Строка 14 – подключение модуля CGI.pm. Здесь не используется
объектно-ориентированный интерфейс, а просто импортируются все функции.
16 строка – получение переданных браузером параметров, если они есть.
Если в процессе закачки файла возникнет ошибка, то скрипт сразу прервет
свою работу и сообщит об ошибке (cgi_error()). При проверке в Perl 5.0 под
Windows я столкнулся с ошибкой – обругали меня за то, что функции
cgi_error() нет. Пришлось сходить на CPAN.org и взять новую версию CGI.pm
(в моем случае это была версия 2.74)
Строки с 22 по 37 выводят форму для загрузки файла. Форма объявляется
как multipart, в HTML-виде это выглядит так:
enctype="multipart/form-data". Строка 29 – специальное поле для загрузки
файла, в браузере оно отображается с кнопочкой «Обзор» (или “Browse”)
справа.
Строки 30 и 31 предлагают пользователю определить, как будет
передаваться файл – как текст (mime-тип: quoted-printable) или как
бинарник (тип: base64)
Форма закончилась – начался разбор параметров. Если скрипт вызывается
первый раз – то здесь его работа закончится, а если пользователь нажимает
кнопку Upload – то далее идет обработка:
Строка 40 – подключение модуля MIME::Lite
Строка 41 и 42 – получение файла, который пользователь загрузил и
информации о нем в переменные $file и $info. $file в зависимости от
контекста - и файл, и строка.
Строки 43-45 создают объект-письмо $msg. Ему присваиваются поля «от
кого», «кому» и «тема» - ведь письмо должно куда-то придти.
Если включен конфигурационный параметр INCLUDE_META – строки с 46 по 56
создают первое вложение в письмо, содержащее служебную информацию. Если
вдруг в этой служебной информации будут русские буквы – то лучше Encoding
поменять на 8bit.
Строки 57-65 выполняют основную работу – создают вложение-файл,
закачанный пользователем. 58-60 строки – выбор типа вложения, в
зависимости от того, который был указан в форме.
Ну и последние строчки скрипта – с 66 по 74 – отправляют сообщение по
почте. Здесь используется метод send_by_smtp(), он более универсален,
однако использует модуль Net::SMTP. Можно также использовать
send_by_sendmail() (тогда sendmail будет искаться в /usr/lib/, что можно
поменять, передав параметр Sendmail=>…, подробнее смотрите в модуле
MIME::Lite)
А если при передаче произошла ошибка при отправке письма – то скрипт
просто выдаст пользователю на страницу все что должен был отправить по
почте.
Вот такой хороший скриптик. Может быть он и не будет работать на вашем
сервере сам по себе, но зато его части очень даже можно использовать в
любом проекте.
=1= #!/usr/bin/perl -w
=2= use strict;
=3= $|++;
=4=
=5= ## configuration
=6=
=7= my $FROM = 'webmaster@your.site';
=8= my $TO = 'upload@your.site';
=9= my $SUBJECT = 'File upload';
=10= my $INCLUDE_META = 1;
=11=
=12= ## end configuration
=13=
=14= use CGI qw(:all);
=15=
=16= my @params = param();
=17= if (my $error = cgi_error()) {
=18= print header(-status => $error);
=19= exit 0;
=20= }
=21=
=22= print
=23= header,
=24= start_html("Upload"),
=25= h1("Upload"),
=26= hr,
=27= start_multipart_form,
=28= table(Tr(td(p('upload:')),
=29= td(filefield('uploaded_file'))),
=30= Tr(td(p('email as type:')),
=31= td(radio_group('type', [qw(binary text)]))),
=35= Tr(td({ -colspan => 2 }, submit))),
=36= end_multipart_form,
=37= hr;
=38=
=39= if (@params) {
=40= require MIME::Lite;
=41= if (my $file = upload('uploaded_file')) {
=42= my $info = uploadInfo($file) or die "info?";
=43= my $msg = MIME::Lite->new
=44= (Type => 'multipart/mixed',
=45= From => $FROM, To => $TO, Subject => $SUBJECT);
=46= if ($INCLUDE_META) {
=47= $msg->attach
=48= (Type => 'TEXT', Encoding => '7bit',
=49= Data => [
=50= "Upload info:n",
=51= (map { "$_ => $info->{$_}n" } sort keys %$info),
=52= "ENV:n",
=53= (map { "$_ => $ENV{$_}n" } sort keys %ENV),
=54= ],
=55= );
=56= }
=57= $msg->attach
=58= ((param('type') eq 'text' ?
=59= (Type => 'TEXT', Encoding => 'quoted-printable') :
=60= (Type => 'BINARY', Encoding => 'base64')),
=64= (FH => $file)),
=65= );
=66= if ($msg->send_by_smtp('localhost')) {
=67= print p("Upload sent by email.");
=68= } else {
=69= print
=70= p("An error occurred... here's what would have been sent:"),
=71= pre($msg->as_string);
=72= }
=73= }
=74= }
=75= print end_html;
|