はい、承知いたしました。パソコン上のどんなファイルでもアップロードできる、最も簡単なPerl CGIスクリプトの例を以下に示します。
この例では、HTMLフォームと、アップロード処理を行うPerlスクリプトの2つのファイルを作成します。
---
## 1. HTMLフォーム (uploader.html)
まず、ファイルをユーザーが選択し、サーバーに送信するためのHTMLフォームを作成します。このファイルを `uploader.html` などの名前で保存してください。
```html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ファイルアップローダー</title>
</head>
<body>
<h1>ファイルをアップロード</h1>
<form action="/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data">
<p>
<input type="file" name="upload_file">
</p>
<p>
<input type="submit" value="アップロード">
</p>
</form>
</body>
</html>
```
**ポイント:**
* `form` タグの `method` 属性は `post` にします。
* `form` タグの `enctype` 属性は `multipart/form-data` にします。これはファイルアップロードに必須です。
* `input type="file"` でファイル選択ダイアログを表示します。`name` 属性(ここでは `upload_file`)はPerlスクリプト側でファイルを受け取る際に使用します。
* `action` 属性には、次に作成するPerl CGIスクリプトのパスを指定します(例: `/cgi-bin/upload.cgi`)。サーバーの設定に合わせて調整してください。
---
## 2. Perl CGIスクリプト (upload.cgi)
次に、アップロードされたファイルをサーバー上で受け取り、保存するPerlスクリプトを作成します。このファイルを `upload.cgi` などの名前で、サーバーのCGI実行可能ディレクトリ(例: `cgi-bin`)に保存してください。
```perl
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use File::Basename;
# --- 設定項目 ---
# ★★★ アップロードされたファイルを保存するディレクトリを指定してください ★★★
# このディレクトリは、Webサーバーのプロセスが書き込み可能なパーミッションを持っている必要があります。
my $upload_dir = "/tmp/uploads"; # 例: Linuxサーバーの場合
# my $upload_dir = "C:/temp/uploads"; # 例: Windowsサーバーの場合
# ------------------
# CGIオブジェクトの作成
my $q = CGI->new;
# HTTPヘッダーの出力 (文字コードをUTF-8に設定)
print $q->header(-charset => 'utf-8');
# HTMLの開始
print <<HTML_START;
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>アップロード結果</title>
</head>
<body>
HTML_START
# アップロード処理
if (my $file_param = $q->param('upload_file')) {
# アップロードされたファイル名を取得
my $original_filename = $file_param;
# セキュリティのため、ファイル名からディレクトリパス情報を取り除く
my $safe_filename = basename($original_filename);
# 注意: これだけでは不十分な場合があります。より厳密なサニタイズを推奨します。
# ファイルハンドルを取得
my $filehandle = $q->upload('upload_file');
if ($filehandle) {
# 保存先ディレクトリが存在しない場合は作成 (簡易的なエラー処理)
unless (-d $upload_dir) {
mkdir $upload_dir or die "ディレクトリを作成できません: $upload_dir ($!)";
}
# 保存するファイルのパス
my $save_path = "$upload_dir/$safe_filename";
# ファイルを開いてバイナリモードで書き込み
open my $out_fh, '>', $save_path or die "ファイルを開けません: $save_path ($!)";
binmode $out_fh;
my $buffer;
while (read($filehandle, $buffer, 1024)) {
print $out_fh $buffer;
}
close $out_fh;
close $filehandle;
print "<h1>アップロード成功!</h1>";
print "<p>ファイル「${safe_filename}」は正常にアップロードされました。</p>";
# print "<p>保存先: ${save_path}</p>"; # デバッグ用に表示。必要に応じてコメントアウトしてください。
} else {
print "<h1>アップロード失敗</h1>";
print "<p>ファイルハンドルを取得できませんでした。</p>";
}
} else {
print "<h1>エラー</h1>";
print "<p>アップロードするファイルが選択されていません。</p>";
}
# HTMLの終了と戻るリンク
print "<hr>";
print "<p><a href='../uploader.html'>アップロードページに戻る</a></p>"; # uploader.html の場所に合わせて調整
print <<HTML_END;
</body>
</html>
HTML_END
exit 0;
```
**ポイント:**
* `use CGI;` でCGIモジュールを使用します。
* `use File::Basename;` でファイル名からパス情報を取り除く `basename` 関数を使用します。
* **`$upload_dir` 変数:** **非常に重要です。** アップロードされたファイルを保存するディレクトリをサーバー上の絶対パスで指定してください。このディレクトリは、Webサーバーの実行ユーザー(例: `apache`, `www-data` など)が書き込み権限を持っている必要があります。
* `$q->param('upload_file')` で、HTMLフォームで指定した `name="upload_file"` のファイル名を取得します。
* `$q->upload('upload_file')` で、アップロードされたファイルの内容を読み取るためのファイルハンドルを取得します。
* セキュリティのため、`basename()` を使ってファイル名からディレクトリトラバーサルの可能性のある情報を取り除いています。 **これは最低限の対策であり、本番環境ではファイル名に使用できる文字を制限したり、拡張子をチェックしたりするなど、より厳密な検証が必要です。**
* ファイルはバイナリモード (`binmode`) で書き込みます。これにより、画像や実行ファイルなど、どんな種類のファイルでも正しく保存できます。
* 簡単なエラー処理(ディレクトリが存在しない場合、ファイルが選択されなかった場合など)を含んでいます。
---
## サーバーへの設置と注意点 ⚠️
1. **Perlのパス:** スクリプトの1行目 `#!/usr/bin/perl` は、サーバー上のPerlインタプリタのパスです。環境によっては `/usr/local/bin/perl` など異なる場合があるので、確認して修正してください。
2. **パーミッション:**
* `upload.cgi` ファイルには実行権限が必要です(例: `chmod 755 upload.cgi`)。
* `$upload_dir` で指定したディレクトリには、Webサーバーのプロセスが書き込みできる権限が必要です。
3. **セキュリティ:**
* **このサンプルは「最も簡単な例」であり、セキュリティ対策は最小限です。**
* **そのまま本番環境で使用するのは危険です。** 悪意のあるユーザーによって、サーバーに不正なファイルがアップロードされたり、既存のファイルが上書きされたりする可能性があります。
* 本番環境で利用する場合は、以下のようなセキュリティ対策を必ず検討・実装してください。
* **ファイルサイズの制限:** 大きすぎるファイルがアップロードされるのを防ぎます。
* **ファイル種類の制限:** 特定の拡張子(例: `.jpg`, `.png`, `.pdf`)のみを許可します。実行可能なスクリプト(`.php`, `.pl`, `.sh` など)のアップロードは特に危険です。
* **ファイル名のサニタイズ:** ファイル名に不正な文字が含まれていないか、より厳密にチェックし、必要であればランダムな文字列などに置き換えます。
* **保存ディレクトリの分離:** アップロードされたファイルをWebから直接アクセスできないディレクトリに保存し、ダウンロード用の別スクリプト経由でのみアクセスできるようにする。
* **ウィルススキャン:** アップロードされたファイルをウィルススキャンする。
4. **エラー処理:** この例のエラー処理は非常に基本的なものです。実際の運用では、より詳細なエラーログを出力したり、ユーザーに分かりやすいエラーメッセージを表示したりすることが望ましいです。
5. **CGIモジュール:** 通常、PerlがインストールされていればCGIモジュールも利用可能ですが、もし利用できない場合はサーバー管理者に相談してください。
---
この例が、Perl CGIでのファイルアップローダー作成の第一歩となれば幸いです。セキュリティには十分注意して開発を進めてください。