尝试在 Perl 中使用 ImageMagick 写入图像和缩略图时出现内部服务器错误
Internal server error when trying to write an image & an thumbnail using ImageMagick in Perl
此 Perl 脚本将图像上传到服务器,然后保存:
- 适合 900x900 像素的画廊图片
- 方形图库缩略图 140x140 像素
- 在 js 文件中添加一行图像和缩略图名称
问题是,脚本有时有效,有时无效。它在每十次尝试中有一两次工作正常。当它不起作用时,它通常 returns "Internal Server Error" 并且不会创建两个文件,也不会在js中添加一行。但在某些情况下,它会创建两个 jpg 文件并且不会在 js 中添加一行(再次返回 "Internal Server Error")。非常奇怪的行为 - 我尝试了各种更改但没有结果。我做错了什么?
#!/usr/bin/perl -w
##
##
use strict;
use CGI;
use CGI::Carp qw ( fatalsToBrowser );
use File::Basename;
use Image::Magick;
$CGI::POST_MAX = 1024 * 70000;
my $safe_filename_characters = "a-zA-Z0-9_.-";
my $pic_upload_dir="../data/photos/gallery";
my $lst_upload_dir="../data";
my $lst_file=$lst_upload_dir."/gallery.js";
my $query=new CGI;
my $PictureIndex=$query->param("Snd_AddPhoto_Idx");
my $photoname=$query->param("AddPhoto");
#upload photo
if ( !$photoname ) {
print "Content-Type: text/plain\n\n";
print "\n\nThere was a problem uploading your photo (try a smaller size).\n";
exit;
}
my ( $phname, $phpath, $phextension ) = fileparse ($photoname, qr/\.[^.]*/);
$photoname = $phname . $phextension;
$photoname =~ tr/ /_/;
$photoname =~ s/[^$safe_filename_characters]//g;
if ( $photoname =~ /^([$safe_filename_characters]+)$/ ) {
$photoname = ;
}
else {
die "Filename contains invalid characters";
}
# force correct filename for temporary file
$photoname="tempphoto_zmm_gallery_".$PictureIndex.$phextension;
my $upload_photohandle = $query->upload("AddPhoto");
open ( UPLOADPHOTO, ">$pic_upload_dir/$photoname" ) or die "$!";
binmode UPLOADPHOTO;
while ( <$upload_photohandle> ) {
print UPLOADPHOTO;
}
close UPLOADPHOTO;
# resize photo
my($photoimage) = Image::Magick->new;
open(PHOTOIMAGE, "$pic_upload_dir/$photoname") or die "Unable to open temporary image file!\n";
$photoimage->Read(file=>\*PHOTOIMAGE);
close(PHOTOIMAGE);
$photoimage->Resize(geometry=>'900x900', blur=>0.8);
$photoimage->Set(Quality=>'75%');
# write ready photo as jpg
my $readyphotoname="pic".$PictureIndex.".jpg";
open(READYIMAGE, ">$pic_upload_dir/$readyphotoname") or die "Unable to write ready image file!\n";
$photoimage->Write(file=>\*READYIMAGE, filename=>$readyphotoname);
close(READYIMAGE);
system("chmod 777 $pic_upload_dir/$readyphotoname");
# resize thumbnail
my($thumbimage) = Image::Magick->new;
open(THUMBIMAGE, "$pic_upload_dir/$photoname") or die "Unable to open temporary image file!\n";
$thumbimage->Read(file=>\*THUMBIMAGE);
close(THUMBIMAGE);
$thumbimage->Resize(geometry=>'140x140^', blur=>0.8);
$thumbimage->Set(gravity=>'Center');
$thumbimage->Crop(geometry=>'140x140+0+0');
$thumbimage->Set(Quality=>'30%');
# write ready thumbnail as jpg
my $readythumbname="tbn".$PictureIndex.".jpg";
open(READYTHUMB, ">$pic_upload_dir/$readythumbname") or die "Unable to write ready image file!\n";
$thumbimage->Write(file=>\*READYTHUMB, filename=>$readythumbname);
close(READYTHUMB);
system("chmod 777 $pic_upload_dir/$readythumbname");
# delete temporary file
my($temporary_file)=$pic_upload_dir."/".$photoname;
unlink($temporary_file) == 0;
# add pic in js gallery list
# prepare new pic record
my $NewGalRecord="GalleryList.push(new Array(\"pic".$PictureIndex.".jpg\",\"tbn".$PictureIndex.".jpg\",\"\",\"\"));\n";
# add to file
open(JS,">>$lst_file") || die "Failed to open $lst_file\n";
printf JS $NewGalRecord;
close JS;
system("chmod 777 $lst_file");
# print confirmation
...
...
...
exit;
我想我已经解决了问题。显然不需要两次读取临时文件。保存 'big' 图像后,我们可以继续操作它,然后再次保存为缩略图。临时文件的双重读取显然会导致冲突。像 'Sharing violation' 这样的东西 - 只是在黑暗中拍摄。但现在脚本工作正常。
另外,远远删除了行 Set(Quality=>)。我不知道他们是否与问题有关,但这将有待于未来的测试。
以下是更改:
# resize photo
my($photoimage) = Image::Magick->new;
open(PHOTOIMAGE, "$pic_upload_dir/$photoname") or die "Unable to open temporary image file!\n";
$photoimage->Read(file=>\*PHOTOIMAGE);
close(PHOTOIMAGE);
$photoimage->Resize(geometry=>'900x900', blur=>0.8);
# write ready photo as jpg
my $readyphotoname="pic".$PictureIndex.".jpg";
open(READYIMAGE, ">$pic_upload_dir/$readyphotoname") or die "Unable to write ready image file!\n";
$photoimage->Write(file=>\*READYIMAGE, filename=>$readyphotoname);
close(READYIMAGE);
system("chmod 777 $pic_upload_dir/$readyphotoname");
# resize thumbnail
$photoimage->Resize(geometry=>'140x140^', blur=>0.8);
$photoimage->Set(gravity=>'Center');
$photoimage->Crop(geometry=>'140x140+0+0');
# write ready thumbnail as jpg
my $readythumbname="tbn".$PictureIndex.".jpg";
open(READYTHUMB, ">$pic_upload_dir/$readythumbname") or die "Unable to write ready image file!\n";
$photoimage->Write(file=>\*READYTHUMB, filename=>$readythumbname);
close(READYTHUMB);
system("chmod 777 $pic_upload_dir/$readythumbname");
# delete temporary file
my($temporary_file)=$pic_upload_dir."/".$photoname;
unlink($temporary_file) == 0;
此 Perl 脚本将图像上传到服务器,然后保存: - 适合 900x900 像素的画廊图片 - 方形图库缩略图 140x140 像素 - 在 js 文件中添加一行图像和缩略图名称
问题是,脚本有时有效,有时无效。它在每十次尝试中有一两次工作正常。当它不起作用时,它通常 returns "Internal Server Error" 并且不会创建两个文件,也不会在js中添加一行。但在某些情况下,它会创建两个 jpg 文件并且不会在 js 中添加一行(再次返回 "Internal Server Error")。非常奇怪的行为 - 我尝试了各种更改但没有结果。我做错了什么?
#!/usr/bin/perl -w
##
##
use strict;
use CGI;
use CGI::Carp qw ( fatalsToBrowser );
use File::Basename;
use Image::Magick;
$CGI::POST_MAX = 1024 * 70000;
my $safe_filename_characters = "a-zA-Z0-9_.-";
my $pic_upload_dir="../data/photos/gallery";
my $lst_upload_dir="../data";
my $lst_file=$lst_upload_dir."/gallery.js";
my $query=new CGI;
my $PictureIndex=$query->param("Snd_AddPhoto_Idx");
my $photoname=$query->param("AddPhoto");
#upload photo
if ( !$photoname ) {
print "Content-Type: text/plain\n\n";
print "\n\nThere was a problem uploading your photo (try a smaller size).\n";
exit;
}
my ( $phname, $phpath, $phextension ) = fileparse ($photoname, qr/\.[^.]*/);
$photoname = $phname . $phextension;
$photoname =~ tr/ /_/;
$photoname =~ s/[^$safe_filename_characters]//g;
if ( $photoname =~ /^([$safe_filename_characters]+)$/ ) {
$photoname = ;
}
else {
die "Filename contains invalid characters";
}
# force correct filename for temporary file
$photoname="tempphoto_zmm_gallery_".$PictureIndex.$phextension;
my $upload_photohandle = $query->upload("AddPhoto");
open ( UPLOADPHOTO, ">$pic_upload_dir/$photoname" ) or die "$!";
binmode UPLOADPHOTO;
while ( <$upload_photohandle> ) {
print UPLOADPHOTO;
}
close UPLOADPHOTO;
# resize photo
my($photoimage) = Image::Magick->new;
open(PHOTOIMAGE, "$pic_upload_dir/$photoname") or die "Unable to open temporary image file!\n";
$photoimage->Read(file=>\*PHOTOIMAGE);
close(PHOTOIMAGE);
$photoimage->Resize(geometry=>'900x900', blur=>0.8);
$photoimage->Set(Quality=>'75%');
# write ready photo as jpg
my $readyphotoname="pic".$PictureIndex.".jpg";
open(READYIMAGE, ">$pic_upload_dir/$readyphotoname") or die "Unable to write ready image file!\n";
$photoimage->Write(file=>\*READYIMAGE, filename=>$readyphotoname);
close(READYIMAGE);
system("chmod 777 $pic_upload_dir/$readyphotoname");
# resize thumbnail
my($thumbimage) = Image::Magick->new;
open(THUMBIMAGE, "$pic_upload_dir/$photoname") or die "Unable to open temporary image file!\n";
$thumbimage->Read(file=>\*THUMBIMAGE);
close(THUMBIMAGE);
$thumbimage->Resize(geometry=>'140x140^', blur=>0.8);
$thumbimage->Set(gravity=>'Center');
$thumbimage->Crop(geometry=>'140x140+0+0');
$thumbimage->Set(Quality=>'30%');
# write ready thumbnail as jpg
my $readythumbname="tbn".$PictureIndex.".jpg";
open(READYTHUMB, ">$pic_upload_dir/$readythumbname") or die "Unable to write ready image file!\n";
$thumbimage->Write(file=>\*READYTHUMB, filename=>$readythumbname);
close(READYTHUMB);
system("chmod 777 $pic_upload_dir/$readythumbname");
# delete temporary file
my($temporary_file)=$pic_upload_dir."/".$photoname;
unlink($temporary_file) == 0;
# add pic in js gallery list
# prepare new pic record
my $NewGalRecord="GalleryList.push(new Array(\"pic".$PictureIndex.".jpg\",\"tbn".$PictureIndex.".jpg\",\"\",\"\"));\n";
# add to file
open(JS,">>$lst_file") || die "Failed to open $lst_file\n";
printf JS $NewGalRecord;
close JS;
system("chmod 777 $lst_file");
# print confirmation
...
...
...
exit;
我想我已经解决了问题。显然不需要两次读取临时文件。保存 'big' 图像后,我们可以继续操作它,然后再次保存为缩略图。临时文件的双重读取显然会导致冲突。像 'Sharing violation' 这样的东西 - 只是在黑暗中拍摄。但现在脚本工作正常。 另外,远远删除了行 Set(Quality=>)。我不知道他们是否与问题有关,但这将有待于未来的测试。 以下是更改:
# resize photo
my($photoimage) = Image::Magick->new;
open(PHOTOIMAGE, "$pic_upload_dir/$photoname") or die "Unable to open temporary image file!\n";
$photoimage->Read(file=>\*PHOTOIMAGE);
close(PHOTOIMAGE);
$photoimage->Resize(geometry=>'900x900', blur=>0.8);
# write ready photo as jpg
my $readyphotoname="pic".$PictureIndex.".jpg";
open(READYIMAGE, ">$pic_upload_dir/$readyphotoname") or die "Unable to write ready image file!\n";
$photoimage->Write(file=>\*READYIMAGE, filename=>$readyphotoname);
close(READYIMAGE);
system("chmod 777 $pic_upload_dir/$readyphotoname");
# resize thumbnail
$photoimage->Resize(geometry=>'140x140^', blur=>0.8);
$photoimage->Set(gravity=>'Center');
$photoimage->Crop(geometry=>'140x140+0+0');
# write ready thumbnail as jpg
my $readythumbname="tbn".$PictureIndex.".jpg";
open(READYTHUMB, ">$pic_upload_dir/$readythumbname") or die "Unable to write ready image file!\n";
$photoimage->Write(file=>\*READYTHUMB, filename=>$readythumbname);
close(READYTHUMB);
system("chmod 777 $pic_upload_dir/$readythumbname");
# delete temporary file
my($temporary_file)=$pic_upload_dir."/".$photoname;
unlink($temporary_file) == 0;