多年来,我使用以下从站点下载的perl代码将文件上传到我们的linux服务器。基本上,用户在html表单中键入用户名和密码,选择要上载的文件,然后单击“提交”。该脚本完成剩下的工作。由于某种原因上周,脚本停止工作。我知道它正在打开要写入的文件,因为我试图注释掉'unlink'行,如果没有写入文件就会删除该文件。它确实打开文件在服务器上写入,但是当我打开文件时,那里什么都没有。我已经尝试更改存储上载文件的目录上的文件权限和所有权,但没有任何结果。任何想法或建议?谢谢!
limit nofile 65535 65535
}
my $DATA_DIR = '/Absolute/path/to/datadir/'; # Path of data directory
my $DEFAULT_UPLOAD_DIR = '/tmp/'; #used only if you don't use password.
my $MAX_SIZE_UPLOAD = 25; # Ko
# File sizes are limited to $MAX_SIZE_UPLOAD (0 No limit), larger files will
# return an 'Internal Server Error'.
my $FORM_URL = 'http://www.yourdomain.com/upload.html';
my $WEBMASTER_EMAIL = 'you@yourdomain.com';
my $DISPLAY_LANG = 'En'; # Fr -> french
my $USE_PASSWORD_PROTECT = 1; # 1 to use password protect 0 else.
my $PASSWORD_FILE = $DATA_DIR.'password.txt'; # Name of Password file
# En: Define all messages and buttons text.
# Fr: Definition des messages et des boutons
my(%NAME_BUTTON, %NAME_HEADTAB, %NAME_TITLE);
if ($DISPLAY_LANG eq 'Fr') {
%NAME_BUTTON = ('exit' => 'Sortir', 'back' => 'Retour', 'add' => 'Ok',
'add_user' => 'Ajouter', 'edit_user' => 'Edit', 'del_user' => 'Supprimer', 'log' => 'Entrer');
%NAME_HEADTAB = ('name' => 'Nom', 'level' => 'Droits', 'user_path' => 'Répertoire utilisateur',
'login' => 'Identifiant', 'password' => 'Mot de passe', 'new_login' => 'Nouvel identifiant',
'new_pass' => 'Nouveau mot de passe', 'conf_pass' => 'Confimer mot de passe',
'admin' => 'Administrateur', 'member' => 'Membre', 'w_path' => "(Chemin inexistant !)");
%NAME_TITLE = ('common_admin' => "eUpload, écran d'administration", 'common_member' => 'eUpload, écran de chargement',
'error_form' => 'Erreur : Formulaire incomplet', 'manage_users' => 'Management des utilisateurs', 'edit_user' => "Editer 'Value_login' utilisateur", 'add_user' => 'Ajout d\'un utilisateur',
'user_saved' => "Utilisateur 'Value_login' savé", 'user_added' => "Nouvel utilisateur 'Value_login' ajouté", 'user_deleted' => "Utilisateur 'Value_new_login' supprimé",
'change_pass' => 'Changer votre mot de passe', 'chpass_invalid' => 'Nouveau mot de passe invalide', 'chpass_updated' => 'Mot de passe de Value_login mis à jour',
'enter_pass' => 'Entrer votre mot de passe', 'invalid_pass' => 'MOT de PASSE INCORECT',
'EU_BadFN' => "Error: Nom de fichier 'Value_FileName' incorrect", 'EU_FExist' => "Error: Fichier 'Value_FileName' existant, impossible de le modifier!",
'EU_Size' => "Error: Erreur de chargement de 'Value_FileName'", 'Upload_Succes' => 'Chargement réussi !',
'Upload_Succes_txt' => "'Value_FileName' (Value_Size bytes, Value_Time s) est sauvé");
} else {
%NAME_BUTTON = ('exit' => 'Exit', 'back' => 'Back', 'add' => 'Ok',
'add_user' => 'Add', 'edit_user' => 'Edit', 'del_user' => 'Remove', 'log' => 'Log in');
%NAME_HEADTAB = ('name' => 'Name', 'level' => 'Level', 'user_path' => "User path",
'login' => 'Login', 'password' => 'Password', 'new_login' => 'New Login',
'new_pass' => 'New password', 'conf_pass' => 'Confim password',
'admin' => 'Administrator', 'member' => 'Member', 'w_path' => "(Path don't exist !)");
%NAME_TITLE = ('common_admin' => "eUpload, administrative display", 'common_member' => "eUpload, upload display",
'error_form' => 'Error : Incomplet form', 'manage_users' => 'Manage Users', 'edit_user' => "Edit 'Value_login' user", 'add_user' => 'Add a user',
'user_saved' => "User 'Value_login' saved", 'user_added' => "New user 'Value_login' added", 'user_deleted' => "User 'Value_new_login' deleted",
'enter_pass' => 'Enter your password', 'invalid_pass' => 'INVALID PASSWORD',
'EU_BadFN' => "Error: Bad Name 'Value_FileName'", 'EU_FExist' => "Error: File 'Value_FileName' exists, can not overwrite !",
'EU_Size' => "Error: Could not upload file: 'Value_FileName'", 'Upload_Succes' => 'Upload uploaded successfully!',
'Upload_Succes_txt' => "'Value_FileName' (Value_Size bytes, Value_Time s) was saved");
答案 0 :(得分:1)
很明显,问题在于在显示的代码之外(之前)上传文件。代码打印到$file_name
,通过清理$file_query
来获取$query
。这是传递给sub的CGI对象本身。我在代码中看不到任何会混淆用于编写$file_name
的数据的内容。
这意味着$file_query
文件句柄的数据(有时)会丢失,因此当您通过read()
循环将其复制到$file_name
时,您什么也得不到。
我可以推荐的一件事是测试被复制到$file_name
的(temp)文件的大小。 请参阅下面的更新,了解如何执行此操作。任何其他诊断都必须在其他地方进行,所以看起来似乎。
另一种(遥远的?)可能性是从$query
拉出的文件句柄已被用于读取(或写入)并且不再指向文件的开头 - 而是指向结尾。这也不在显示的代码中。 更新:可能值得在seek $query_file, 0, 0
循环之前尝试read
,以'回放'到文件的开头。
代码可以改进但我不知道它是如何导致这个问题的。
<强>更新强>
脚本通过read($file_query, ...)
读取,其中$file_query
先前由
$_ = $file_query = $query->param('file')
query->param
返回事物的名称,而read
需要文件句柄。通过CGI的方便,param
返回的内容也可以用作文件句柄。但是,通过方法$query->upload('file')
从CGI对象中正确获取文件句柄。
然后值得尝试通过upload
方法获取文件句柄,并在read
循环中使用它,而不是$file_query
。请参阅File upload文档中的CGI部分。
更新
来自CGI.pm docs中的File upload
处理上传的文件时,CGI.pm会在硬盘上创建一个临时文件,并将文件句柄传递给该文件。
检查此文件以查看该文件是否完全进入服务器。在upload()
sub之前执行此操作。链接的文档给我们
my $fh_tmp = $query->upload( 'file' );
my $tmpfilename = $query->tmpFileName( $fh_tmp );
现在可以查询$tmpfilename
的大小,例如,您的代码使用相同的stat
来检查$file_name
大小,或者只使用Perl的file-test operators
(if -z $tmpfilename) { print "Empty file (exists but zero size)!\n" }
如果 文件为零大小,则表示问题较早。