Reputation: 2413
When I try to print an image to STDOUT
in a Perl CGI script, the image gets clipped when viewed in the browser.
Here is the following code:
if ($path =~ m/\.jpe?g$/i)
{
my $length = (stat($path))[7];
$| = 1;
print "Content-type: image/jpg\r\n";
print "Content-length: $length\r\n\r\n";
open(IMAGE,"<$path");
binmode(IMAGE);
binmode(STDOUT);
my ($image, $buff);
read IMAGE, $buff, $length;
syswrite STDOUT, $buff, $length;
close IMAGE;
}
Upvotes: 2
Views: 344
Reputation: 2413
FYI: I have come to the conclusion that the images are in fact corrupt, though they are fully viewable in Windows File Explorer.
The FireFox browser shows the Images clipped(no matter how they are accessed, so I guess this is no longer a Perl problem), but the Safari Browser displays them completely.
The images were re sampled from using Java's imageIO in "jpg" mode. I just changed the mode to "png", and now the newly generated images are showing perfectly in all browsers. So this was actually a Java imageIO issue.
It is solved.
Thank you everyone for your responses.
Upvotes: 0
Reputation: 118128
If you really want to read the entire file into memory before serving, use File::Slurp:
#!/usr/bin/perl
use strict; use warnings;
use CGI::Simple;
use File::Slurp;
use File::stat;
local $| = 1;
my $cgi = CGI::Simple->new;
my $st = stat($path) or die "Cannot stat '$path'";
print $cgi->header(
-type => 'image/jpeg',
-length => $st->size,
);
write_file(\*STDOUT, {binmode => ':raw'},
\ read_file( $path, binmode => ':raw' )
);
However, reading the entire file will consume large amounts of memory for large images. Therefore, see How can I serve an image with a Perl CGI script?.
Upvotes: 5
Reputation: 59927
EDIT: as the stat
doesn't seem to be problem, some more ideas:
try using unbuffered instead of buffered reading, ie. use sysread
instead of read
. or the other way round: use both buffered read
and write
. also, try commenting out the $|
. see Suffering from Buffering? for details on perl buffered io. see also How can I serve an image with a Perl CGI script? here on SO for an apparently working solution. EDIT END
you are using the wrong stat
field. (stat($path))[10]
is ctime: inode change time in seconds since the epoch. it should be (stat($path))[7]
, size: total size of file, in bytes.
Upvotes: 2