- ベストアンサー
PERLでファイルのアップロード機能を作成する方法
- PERLを使ってファイルのアップロード機能を作成する方法についてご教授願います。
- 質問文章では、2つのパターンを試していますが、パターン1ではOPEN関数がうまく機能しないため、解決策を知りたいです。
- また、パターン2ではファイルの内容が画面に表示されることが確認できますが、パターン1ではWhile文に入らない原因がわかりません。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
CGI.pm は、アップロードフィールドで指定されたファイルを読み込み、テンポラリファイルに書き出してくれます。 > $filename = $query->param('temp1'); # ファイル名(フルパス)取得 によって取得した $filename はアップロードフィールドに指定されたファイル名であって、CGI.pm が作成したテンポラリファイルの名前ではありません。 ですから、その名前をファイル名として open することはできません。 また、$filename はテンポラリファイルのファイルハンドルでもあります。 このためパターン2はうまくいくのです。 ただし、ユーザがアップロードフィールドに有効でない値を指定した場合、$filename をファイルハンドルとして使用できないことがあります。 アップロードに関しては、この曖昧なファイルハンドルを返す param の代わりに、upload メソッドを使うことが推奨されています。 upload はテンポラリファイルへのファイルハンドルを返し、アップロードフィールドの値が有効でないと undef を返します。 $fh = $query->upload('temp1'); if ($fh) { while($bytesread = read($fh, $buffer, $BUFSZ)) { : } } のようにするとよいでしょう。
その他の回答 (2)
- leaz024
- ベストアンサー率75% (398/526)
> パターン2でprint $fileとやるとファイルの内容が > そのまま表示されます。 > これが何故16進数で表示されないかが疑問です。。。 読み込んだファイルを表示しているだけですから、それは当然です。 また、数値ならバイナリ形式というのもありますが、文字列はそれ自体がバイナリですから、$file はバイナリデータであるといえます。 (ただし、Windows系では改行の扱いに注意が必要です。) もし、たとえば「XYZ」という文字列を「58 59 5A」のように表示したいのであれば、 my @bin = map {sprintf "%02X", $_} unpack("C*", $file); for (my $i = 0; $i <= $#bin; $i += 16) { print "@bin[$i..$i+15]\n"; } としてください。 これはバイナリエディタなどでの表示に近いものですが、これがバイナリデータなのではありません。 あくまで可視キャラクタを使って内部表現を見せているだけです。 もし、DBのカラムが「CHAR(**) BINARY」などのようになっているのなら、$file の値をそのまま入れればよいはずです。 > あと、いろんなサンプルを見るとパターン1の様に > OPENしてREADすればできる!とあるのに それは普通のファイルの話ではないでしょうか。 少なくとも CGI.pm を使ったファイルのアップロードで、読み込んだファイルを open で開くというのは聞いたことがありません。 パターン2、もしくは upload メソッドを使った方法で大丈夫ですよ。
補足
何度もすいません。 質問した後に色々試してみたのですが、 パターン2の$file_nameがファイルハンドラと なっていたみたいで、binmode($file_name)として readすることができました。 これをMySQLのMEDIUMBLOD型に格納してダウンロード させる機能を作りました。 しかし、アップしたファイルの内容とは異なる内容 (文字化け)でファイルが表示されてしまいました。 う~ん、なんでだろう?
- leaz024
- ベストアンサー率75% (398/526)
> 実際にやりたいのは、パターン1の方法なのですが 恐らく、 (1).アップロードされたファイルの内容を取得する($file へ格納) (2).その内容をデータベースに登録する($file をDBへINSERT) という手順になると思うのですが、パターン1もパターン2も、(1)に関するコードですよね? 同じ処理を行うコードなので、パターン1にこだわる必要はないと思うのですが、パターン1でなければならないのはどの点なのでしょうか? アップロードされたファイルの内容を $file に入れることはできているのですから、後は DBI モジュールなどを使ってDBへ放り込む(2)のコードを書けばよいように思うのですが、どうでしょうか? 何か勘違いしているのかも知れませんので、具体的に何が問題なのかを補足ください。 (パターン1の while が実行されないのは open が失敗しているからだ、というのはいいですよね?)
補足
度々ありがとうございます。 確かに同じ結果が得られるのであれば、 パターンにこだわる必要はないのですが、 パターン2でprint $fileとやるとファイルの内容が そのまま表示されます。 これが何故16進数で表示されないかが疑問です。。。 あと、いろんなサンプルを見るとパターン1の様に OPENしてREADすればできる!とあるのに、何故OPEN できないのか、どうすればOPENしてREADしてできるよう になるのかが分かりません。 初歩的な質問で申し訳ありませんが教えて下さい。
補足
ご回答ありがとうございます。 paramの変わりにuploadメソッドを使うのが推奨されているのですか。。。 スミマセン、初心者な者ですからよくわかっていないのですが、お教え頂いた方法ってパターン2ですよね? 実際にやりたいのは、パターン1の方法なのですが、 どうのようにすればアップロードされたファイルを バイナリでデータベースに登録することができるのでしょうか?