2013-08-03 20 views
0

我想將文件句柄存儲到一個全局散列中,並且在沒有顯示CGI對象的情況下讀取()它在子例程中,但是我發現它不起作用(導致零大小的輸出文件)。CGI.pm:子程序之間丟失全局散列中的文件句柄?

這裏是簡化的Perl代碼:

#!/usr/local/bin/perl 

use CGI; 
use vars qw(%in); 

&init_hash; 
$fname = &process_uploaded_file if($in{'upfile'}); 
$fsize = -s $fname; 

print "Content-Type: text/plain\r\n\r\n"; 
print "in{'upfile'}=",$in{'upfile'},"\r\n"; 
print "in{'desc'}=",$in{'desc'},"\r\n"; 
print "fname=",$fname,"\r\n"; 
print "fsize=",$fsize,"\r\n"; 

sub init_hash{ 
    my $q = new CGI; 
    $in{'desc'} = $q->param('desc'); 
    $in{'upfile'} = $q->param('upfile'); 
    $in{'upfh'} = $q->upload('upfile') if($in{'upfile'}); 
} 

sub process_uploaded_file{ 
    my $fname = time.'.bin'; 
    open(OUT,'>',$fname) || die('open file failed'); 
    while(my $read = read($in{'upfh'}, my $buff, 4096)){ 
     print OUT $buff; 
    } 
    close(OUT); 
    eval { close($in{'upfh'}); }; 
    return $fname; 
} 

編輯:我應該提供Perl和cgi.pm版本。 Perl版本:這是爲MSWin32-x86-多線程 (有8個註冊的補丁,請參閱perl -V以獲取更多詳細信息)構建的perl 5,版本12,subversion 2(v5.12.2) $ CGI :: VERSION = '3.50';

+0

我想你需要檢查信息是否從文件$中讀取{'upfh'} –

+0

@KostiaShiian,但該文件是創建和寫入的。如果我將process_uploaded_file的內容追加到init_hash,並註釋掉第7行,它就可以工作。 – Roy

回答

2

你的代碼有太多錯誤。

首先你的問題:你正在試圖優化哪裏沒有優化。在實際訪問它們之前,CGI對象的臨時文件將被刪除。當你延長CGI對象的生命週期時,你的代碼應該可以工作。通過將其添加到%in散列。


  • 始終use strict; use warnings;。沒有任何藉口。
  • 全局變量聲明爲ourvars編譯指示是一種歷史文物。但請不要使用全局變量,因爲它們在這裏是不需要的。
  • 不要調用像&foo這樣的函數,除非你能告訴我什麼恰恰是這樣做。直到你有這方面的知識:foo()
  • 使用CGI對象的header方法來寫頭:$q->header('text/plain')
  • \n可能不是你認爲的那樣。執行binmode STDOUT以刪除當前應用的 PerlIO層。雖然相當於\r\n,但編寫\015\012可能會更清楚,以證明您關心實際字節。
  • 你可以插入變量到字符串,你知道。您還可以指定一個字符串,它是通過設置$\每個print後附加:

    { 
        local $\ = "\015\012"; 
        print "in{'upfile'}=$in{'upfile'}"; 
        print "in{'desc'}=$in{'desc'}"; 
        print "fname=$fname"; 
        print "fsize=$fsize"; 
    } 
    
  • 不要使用裸字的文件句柄。而不是open OUT, "<", $fname你應該open my $outfh, "<", $fname
  • 你爲什麼把一個close放在eval?我不明白這應該如何die
+0

謝謝。將$ q添加到%in就可以了。這些代碼是遺留代碼(cca 2003),可以在舊服務器上運行良好。 – Roy