Perl で、アップロードしたファイルを処理する

Perl の場合は、CGI として動作させる場合は、必ず
print qq|Content-type: text/html\n\n|;
という行が必要な以外は、PHP とほとんど同じである。 アップロードには、いつも使っているおなじみの CGI モジュールを使う。
use CGI;
そうすると、以下のようにアクセスできる。
our $CGI = new CGI;
...
my $xml = $CGI->param('file');
$xml はファイルポインタが入っている。通常は open(IN, "..."); などするときの IN にあたるものである。以下は、コード。アップロードする側の HTML ファイルは PHP でアップロードファイルを処理するで紹介したのと同じ。
#!/usr/bin/perl

use strict;
use CGI;

our $CGI = new CGI;

print qq|Content-type: text/html\n\n|;
init();

sub init() {

    # XMLパーサー作成 ('UTF-8')
    my $xml_parser = new XML::Parser(    ProtocolEncoding => 'UTF-8',
                                        Handlers=>{    Start=>\&startElement,
                                                    End  =>\&endElement,
                                                    Char =>\&dataHandler    });
    # ファイルのオープンはいらない。input タグで指定した name 属性がそのままファイルハンドルになる
    my $xml = $CGI->param('file');

    # XMLパース処理
    $xml_parser->parse($xml) or    die "XML error: $xml_parser";

    # ファイルクローズ
    close($xml);
}

1;
Perl の場合は、CGI として動作させる場合は、必ず
print qq|Content-type: text/html\n\n|;
という行が必要な以外は、PHP とほとんど同じである。 アップロードには、いつも使っているおなじみの CGI モジュールを使う。
use CGI;
そうすると、以下のようにアクセスできる。
our $CGI = new CGI;
...
my $xml = $CGI->param('file');
$xml はファイルポインタが入っている。通常は open(IN, "..."); などするときの IN にあたるものである。以下は、コード。アップロードする側の HTML ファイルは PHP でアップロードファイルを処理するで紹介したのと同じ。
#!/usr/bin/perl

use strict;
use CGI;

our $CGI = new CGI;

print qq|Content-type: text/html\n\n|;
init();

sub init() {

    # XMLパーサー作成 ('UTF-8')
    my $xml_parser = new XML::Parser(    ProtocolEncoding => 'UTF-8',
                                        Handlers=>{    Start=>\&startElement,
                                                    End  =>\&endElement,
                                                    Char =>\&dataHandler    });
    # ファイルのオープンはいらない。input タグで指定した name 属性がそのままファイルハンドルになる
    my $xml = $CGI->param('file');

    # XMLパース処理
    $xml_parser->parse($xml) or    die "XML error: $xml_parser";

    # ファイルクローズ
    close($xml);
}

1;

PHP で、アップロードしたファイルを処理する

まず、アップロードする側の HTML は以下のようになる。特に、
<form enctype="multipart/form-data"...>
<input type="file" name="file" /&gt
の指定が必要となる。ここで input type="file" name="file" となっている name 属性のところに書いてある値 (この場合は file) が、サーバ側で利用される。
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </head>
  <body>
<!--
    <form enctype="multipart/form-data" action="gmap_excel.php" method="post">
-->
    <form enctype="multipart/form-data" action="gmap_excel.cgi" method="post">
      <input type="hidden" name="MAX_FILE_SIZE" value="2000000" />
      <table width="600">
        <tr><td>Names file:</td><td><input type="file" name="file" /><input type="submit" value="Upload" /></td></tr>
      </table>
    </form>
  </body>
</html>
サーバ側の PHP は以下の通り (例として、アップロードするファイルは XML としている)。肝心なのは、以下の3行である。
<?php

// ファイルのオープン
$fp = fopen($_FILES['file']['tmp_name'], 'r')
or die(
'Cannot open an XML file: ' . $_FILES['file']['tmp_name']);

// ファイルを読み込む
while ($data = fread($fp, 4096)) {
...
}

?>
<?php

init
();

function
init() {

 
// XMLパーサー作成 ('UTF-8')
 
$xml_parser = xml_parser_create('UTF-8');

 
// 大文字変換を行わない
 
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);

 
// start および end 要素のハンドラを設定する
 
xml_set_element_handler($xml_parser, 'startElement', 'endElement');
 
xml_set_character_data_handler($xml_parser, 'characterData');

 
// ファイルのオープン
 
$fp = fopen($_FILES['file']['tmp_name'], 'r')
  or die(
'Cannot open an XML file: ' . $_FILES['file']['tmp_name']);

 
// ファイルを読み込む
 
while ($data = fread($fp, 4096)) {

   
// XMLパース処理
   
if (!xml_parse($xml_parser, $data, feof($fp))) {

     
// パースエラー処理
     
die(sprintf("XML error: %s at line %d",
       
xml_error_string(xml_get_error_code($xml_parser)),
       
xml_get_current_line_number($xml_parser)));
    }
  }

 
// XMLパーサの開放
 
xml_parser_free($xml_parser);
}

?>
まず、アップロードする側の HTML は以下のようになる。特に、
<form enctype="multipart/form-data"...>
<input type="file" name="file" /&gt
の指定が必要となる。ここで input type="file" name="file" となっている name 属性のところに書いてある値 (この場合は file) が、サーバ側で利用される。
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </head>
  <body>
<!--
    <form enctype="multipart/form-data" action="gmap_excel.php" method="post">
-->
    <form enctype="multipart/form-data" action="gmap_excel.cgi" method="post">
      <input type="hidden" name="MAX_FILE_SIZE" value="2000000" />
      <table width="600">
        <tr><td>Names file:</td><td><input type="file" name="file" /><input type="submit" value="Upload" /></td></tr>
      </table>
    </form>
  </body>
</html>
サーバ側の PHP は以下の通り (例として、アップロードするファイルは XML としている)。肝心なのは、以下の3行である。
<?php

// ファイルのオープン
$fp = fopen($_FILES['file']['tmp_name'], 'r')
or die(
'Cannot open an XML file: ' . $_FILES['file']['tmp_name']);

// ファイルを読み込む
while ($data = fread($fp, 4096)) {
...
}

?>
<?php

init
();

function
init() {

 
// XMLパーサー作成 ('UTF-8')
 
$xml_parser = xml_parser_create('UTF-8');

 
// 大文字変換を行わない
 
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);

 
// start および end 要素のハンドラを設定する
 
xml_set_element_handler($xml_parser, 'startElement', 'endElement');
 
xml_set_character_data_handler($xml_parser, 'characterData');

 
// ファイルのオープン
 
$fp = fopen($_FILES['file']['tmp_name'], 'r')
  or die(
'Cannot open an XML file: ' . $_FILES['file']['tmp_name']);

 
// ファイルを読み込む
 
while ($data = fread($fp, 4096)) {

   
// XMLパース処理
   
if (!xml_parse($xml_parser, $data, feof($fp))) {

     
// パースエラー処理
     
die(sprintf("XML error: %s at line %d",
       
xml_error_string(xml_get_error_code($xml_parser)),
       
xml_get_current_line_number($xml_parser)));
    }
  }

 
// XMLパーサの開放
 
xml_parser_free($xml_parser);
}

?>
Posted on 2005-11-25 by yas |

Perl で、HTML 文書中にあるリンクを置換する

以下は、HTML 文書中にあるリンクを任意の文字列に置換するスクリプトであるが、他のタグでもいろいろと応用が利くと思われる。
#!/usr/bin/perl

use LWP::UserAgent;
use HTTP::Status;
use HTTP::Response;

our $URL = 'https://perltips.twinkle.cc/'; # アクセスする URL

my $proxy = new LWP::UserAgent;
$proxy->agent('your own created browser name here');
$proxy->timeout(60);

my $response = $proxy->request(HTTP::Request->new('GET' => $URL));
my $content = $response->content;

my %tags = (

    'img'  => 'src',
    'a'    => 'href',
    'link' => 'href',
    'td'   => 'background',
    'form' => 'action'
);

my $data = $content;

skip_others: while($data =~ s/<([^>]*)>// && $i++ < 10000) { # 無限ループに陥るのを防ぐ

    my $in_brackets = $1;

    foreach $key (keys %tags) {

        if($in_brackets =~ /^\s*$key\s+/i) {

            if($in_brackets =~ /\s+$tags{$key}\s*=\s*["']([^"']*)["']/i
            || $in_brackets =~ /\s+$tags{$key}\s*=\s*([^\s]+)/i        ) {

                my $link =  $1;

                $link =~ s/[\n\r]//g;
                $link =~ s/\./\\./g;
                $link =~ s/\?/\\?/g;

                $content    =~
                    s/\s*=\s*["']*$link["']*/=<<<ここに置換文字列を書く>>>/
                    if $link !~ m/mailto:/i
                    && $link !~ m/javascript/i;

                next skip_others;
            }
        }
    }
}

1;
以下は、HTML 文書中にあるリンクを任意の文字列に置換するスクリプトであるが、他のタグでもいろいろと応用が利くと思われる。
#!/usr/bin/perl

use LWP::UserAgent;
use HTTP::Status;
use HTTP::Response;

our $URL = 'https://perltips.twinkle.cc/'; # アクセスする URL

my $proxy = new LWP::UserAgent;
$proxy->agent('your own created browser name here');
$proxy->timeout(60);

my $response = $proxy->request(HTTP::Request->new('GET' => $URL));
my $content = $response->content;

my %tags = (

    'img'  => 'src',
    'a'    => 'href',
    'link' => 'href',
    'td'   => 'background',
    'form' => 'action'
);

my $data = $content;

skip_others: while($data =~ s/<([^>]*)>// && $i++ < 10000) { # 無限ループに陥るのを防ぐ

    my $in_brackets = $1;

    foreach $key (keys %tags) {

        if($in_brackets =~ /^\s*$key\s+/i) {

            if($in_brackets =~ /\s+$tags{$key}\s*=\s*["']([^"']*)["']/i
            || $in_brackets =~ /\s+$tags{$key}\s*=\s*([^\s]+)/i        ) {

                my $link =  $1;

                $link =~ s/[\n\r]//g;
                $link =~ s/\./\\./g;
                $link =~ s/\?/\\?/g;

                $content    =~
                    s/\s*=\s*["']*$link["']*/=<<<ここに置換文字列を書く>>>/
                    if $link !~ m/mailto:/i
                    && $link !~ m/javascript/i;

                next skip_others;
            }
        }
    }
}

1;

Perl で、ライブラリのパスを指定する方法

いくつか方法がある。
方法1:

use lib 'ライブラリのあるパス';
use Foo::Bar;
...
方法2:

unshift @INC, 'ライブラリのあるパス';
use Foo::Bar;
...

とかして、強制的に @INC に入れる。
方法3:

スクリプト中で強制的にインクルードするライブラリへのパスを含めちゃう

(スクリプトの先頭、おなじみ #!/usr/bin/perl の部分に -I オプションを付ける)

#!/usr/bin/perl -I/home/yourdir/lib

方法4:

perl -e shell -MCPAN じゃなくてアーカイブのやつをインストールするには、<br />ライブラリの tar.gz を解凍して

# perl Makefile.PL PREFIX=/home/yourname/yourdir/lib
# make install

とかする。PREFIX= でインストール先を指定できる。
Perl のライブラリには必ず Makefile.PL というファイルが入っているから<br />PREFIX オプションを指定してダメだった場合、このファイルの中身をチェックする必要がある。
いくつか方法がある。
方法1:

use lib 'ライブラリのあるパス';
use Foo::Bar;
...
方法2:

unshift @INC, 'ライブラリのあるパス';
use Foo::Bar;
...

とかして、強制的に @INC に入れる。
方法3:

スクリプト中で強制的にインクルードするライブラリへのパスを含めちゃう

(スクリプトの先頭、おなじみ #!/usr/bin/perl の部分に -I オプションを付ける)

#!/usr/bin/perl -I/home/yourdir/lib

方法4:

perl -e shell -MCPAN じゃなくてアーカイブのやつをインストールするには、<br />ライブラリの tar.gz を解凍して

# perl Makefile.PL PREFIX=/home/yourname/yourdir/lib
# make install

とかする。PREFIX= でインストール先を指定できる。
Perl のライブラリには必ず Makefile.PL というファイルが入っているから<br />PREFIX オプションを指定してダメだった場合、このファイルの中身をチェックする必要がある。
Posted on 2005-11-21 by yas |