2

朋友们,
我一直在网上搜索使用 Perl 将图像显示到网络浏览器的解决方案,但没有找到适合我的解决方案。
我尝试了可能的解决方案,例如:
如何使用 Perl 显示图像
输出图像数据
从脚本返回图像
,但没有一个适用于我正在做的事情。我想拒绝客户端访问图像(或者甚至只是将图像文件放在 www 根目录之外)并将其发送到服务器端。
这是我正在做的一个例子:

在我的主 perl 文件中:

...
my $query = CGI->new();

sub main {
### This grabs page content from a module, depending on the page name.
### The module returns the HTML.
my $html = get_page('page', 'session');

### Perform any special conditionals here before printing the header...

print $query->header(some cookie/session data here);
print $html

}

在其中一个模块中:

sub return_page_content {

return <<HTML;
<html>
  <body>
    <img src="GET IMAGE HERE..." />
  </body>
</html>
HTML
}

我曾考虑在临时目录位置创建图像的副本,但这似乎会破坏将图像保持在客户端访问之外的整个目的。
可能的解决方案不会生成图像。我不确定从这里去哪里,所以我希望这里有人有想法。太感谢了!
如果我需要提供其他信息,请告诉我。我觉得这可能对很多人都有好处。我希望至少 ;-)

4

4 回答 4

3

对于简单的“将文件发送到浏览器解决方案”,只需向浏览器发送正确的标题(让浏览器知道接下来会发生什么),然后打开图像并将内容打印到 STDOUT。

select(STDOUT); $| = 1;   #unbuffer STDOUT
print "Content-type: image/png\n\n";

open (IMAGE, '<', '/image_outside_webroot/image.png');
print <IMAGE>;
close IMAGE;

一旦工作正常,请查看ImageMagick。您可以进行各种即时、有趣的图像处理(调整大小、着色等)

您的 cgi 脚本将包含如下所示的代码:

select(STDOUT); $| = 1;   #unbuffer STDOUT

my $image = Image::Magick->new();
my $x = $image->Read(filename =>"/images_outside_web_root/image1.png");

#some manipulation of the image here

print "Content-type: image/png\n\n";
binmode STDOUT;
$x = $image->Write(.png:-');

您可以在上面链接的网站上阅读更多相关信息。

希望有帮助。

于 2012-12-13T03:21:37.737 回答
2

好吧,事实证明这不起作用的原因是因为我完全忘记了我没有在标准 cgi_bin 目录之外使用 CGI 进行操作。相反,我使用 .htaccess 文件告诉服务器如何以及何时将根目录中的文件解释为 cgi。

所以,这就是我最终在我的图像碟形脚本中使用的:

imagedish.pm

use CGI;

my $cgi = new CGI;

open (IMAGE, 'logo.png');
my $size = -s "logo.png";
my $data;
read IMAGE, $data, $size;
close (IMAGE);

print $cgi->header(-type=>'image/png'), $data;

这成功了,就像它从一开始就应该做的那样,但是在我的 .htaccess 文件中,我添加了:

<files imagedish.pm>
SetHandler cgi-script
</files>

这就是诀窍(嗯,那个,以及进入终端并运行 chmod +x imagedish.pm 以使其可执行)!当然,接下来的步骤是额外的安全措施,但至少它现在正在工作!:-)

完整的解决方案:主文件:

!/usr/bin/perl 

use CGI;
use CGI::Carp qw(fatalsToBrowser);
use CGI::Session qw/-ip-match/;
use DBI;
use strict;
use warnings;

# Variables
my $query = CGI->new();
my %vars = $query->Vars();

sub main {

    my $p1 = $vars{p1};

    $p1 = 'Home' if (!$p1);


    my $html = get_page();

    #I use this method in case we have multiple sessions
    #I've omitted how I acquire the session, as this is not part of the solution ;-)
    print $query->header(-cookie=>[$query->cookie($vars{p1}=>$session->id)]);
    print $html;
}

sub get_page {
    return <<HTML;
<!DOCTYPE HTML>
<html>
    <head>
        <title>Image Disher</title>
        <link rel="shortcut icon" href="images/favicon.ico" />
        <link href="css/style.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <div class="container">
            <div class="addentry">
                <div class="iaddentry">
                    <form name="client" action="" method="POST">
                        <div class="form-header" action="">
                            <center>
                                <img src="imagedish.pm" width="305" alt=""/><br>
                            </center>
                            <br>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>
HTML
}


main();

在这里,img 标签查找源“imagedish.pm”,一旦找到,.htaccess 文件会告诉它作为 CGI 脚本执行。那时,它会适当地提供信息,而不是像以前那样。

请注意,这不是最安全的方法,但它让我朝着正确的方向前进。

于 2012-12-14T18:24:20.880 回答
1

还有一种方法是使用<img src="data:image/...,base64,...">格式嵌入图像。

这会破坏浏览器缓存,并且不适用于非常大的图像。但是,如果将图像构建为初始页面加载的一部分更容易,或者您不希望通过文件系统管理/服务它们的麻烦,那么它很有用。

#!/user/bin/perl
use warnings; use strict;
use MIME::Base64 qw();

sub return_page_content {
    my $image_type = shift;
    my $image_data = shift;

    my $image_base64 = MIME::Base64::encode($image_data);
    $image_base64 =~ s{\n}{}g; # lose newlines

return <<HTML;
<html>
  <body>
    <img src="data:image/${image_type};base64,${image_base64}" />
  </body>
</html>
HTML
}

my $image_path =  "/tmp/test.jpg";
open(my $fh, '<', $image_path)
    or die "unable to open file $image_path: $!";

binmode($fh);
my $image_data = do {local $/; <$fh>};
close($fh);

print return_page_content("jpeg", $image_data);
于 2012-12-13T03:46:56.370 回答
1

您找到的链接(第一个除外)描述了如何执行此操作,我认为您只是对交付图像交付带有 img 标签的 html 文件之间的区别感到困惑。请记住,当您的浏览器在解析 html 文件并遇到 img 标签时,它会获取标签中的 src url 并对其发出额外的 get 请求。

尝试使用 curl、wireshark 等从图像请求中捕获原始输出。结果就是您想要尝试创建的结果。只需返回内容类型 http 标头,然后是二进制图像数据。

再看一下这个例子,去掉 random_file 子,并替换这一行:

    my $image = random_file( IMAGE_DIRECTORY, '\\.(png|jpg|gif)$' );

有了这个:

    my $image = "path to an image file accessible by www-user";

希望一旦您开始工作并了解它在做什么,您就会知道下一步需要做什么。

于 2012-12-13T02:53:35.400 回答