Perl CGI从文件向浏览器显示图像

时间:2012-12-13 02:03:11

标签: perl cgi


我一直在网上寻找一个解决方案,用Perl向Web浏览器显示图像,并且发现没有什么对我有用。
我尝试过可能的解决方案,例如:
How To Display an Image with Perl
Outputting Image Data
Return an Image From a Script
并且它都不适用于我正在做的事情。我想拒绝客户端访问图像(或者甚至只是将图像文件放在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 个答案:

答案 0 :(得分: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:-');

您可以在上面链接的网站上阅读有关此内容的更多信息。

希望有所帮助。

答案 1 :(得分:1)

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

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

再看看this示例,并删除random_file子,并替换此行:

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

用这个:

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

希望一旦你工作并了解它正在做什么,你就会知道接下来需要做什么。

答案 2 :(得分: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);

答案 3 :(得分:1)

嗯,事实证明这不起作用的原因是因为我完全忘记了我没有使用CGI超出标准的cgi_bin目录。相反,我使用.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以使其可执行)!当然接下来的步骤是额外的安全措施,但至少它现在正在运行! :-)

完整的解决方案: mainfile:

!/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脚本执行。在这一点上,它适当地剔除信息,而不是像以前那样。

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