aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet
diff options
context:
space:
mode:
authorMatthew Somerville <matthew@mysociety.org>2012-03-08 14:05:01 +0000
committerMatthew Somerville <matthew@mysociety.org>2012-03-08 14:05:01 +0000
commit1a5baa677635b0fb981bd4cf83e1843f8d5ef8ab (patch)
treef86ee8c99fd6269b925640dc2bb3ebb44ee279ce /perllib/FixMyStreet
parent410d1f1edc737d1d60e83f90053fe028eff3de30 (diff)
Store full size photos that are uploaded on filesystem, put hash in database. Fixes #9, basics for #209 (needs light box adding).
Diffstat (limited to 'perllib/FixMyStreet')
-rw-r--r--perllib/FixMyStreet/App.pm25
-rw-r--r--perllib/FixMyStreet/App/Controller/Open311.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Photo.pm46
-rwxr-xr-xperllib/FixMyStreet/App/Controller/Questionnaire.pm5
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm94
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/Update.pm5
-rwxr-xr-xperllib/FixMyStreet/App/Controller/Rss.pm4
-rw-r--r--perllib/FixMyStreet/DB/Result/Comment.pm11
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm11
9 files changed, 97 insertions, 106 deletions
diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm
index 0582d88c9..262379b79 100644
--- a/perllib/FixMyStreet/App.pm
+++ b/perllib/FixMyStreet/App.pm
@@ -11,6 +11,7 @@ use mySociety::EmailUtil;
use mySociety::Random qw(random_bytes);
use FixMyStreet::Map;
+use Path::Class;
use URI;
use URI::QueryParam;
@@ -415,6 +416,30 @@ sub render_fragment {
$c->view('Web')->render($c, $template, $vars);
}
+=head2 get_photo_params
+
+Returns a hashref of details of any attached photo for use in templates.
+Hashref contains height, width and url keys.
+
+=cut
+
+sub get_photo_params {
+ my ($self, $key) = @_;
+ $key = ($key eq 'id') ? '' : "/$key";
+
+ return {} unless $self->photo;
+
+ my $photo = {};
+ if (length($self->photo) == 40) {
+ $photo->{url_full} = '/photo' . $key . '/' . $self->id . '.full.jpeg';
+ } else {
+ ( $photo->{width}, $photo->{height} ) =
+ Image::Size::imgsize( \$self->photo );
+ }
+ $photo->{url} = '/photo' . $key . '/' . $self->id . '.jpeg';
+
+ return $photo;
+}
=head1 SEE ALSO
diff --git a/perllib/FixMyStreet/App/Controller/Open311.pm b/perllib/FixMyStreet/App/Controller/Open311.pm
index fe1494b95..34e2b7cd3 100644
--- a/perllib/FixMyStreet/App/Controller/Open311.pm
+++ b/perllib/FixMyStreet/App/Controller/Open311.pm
@@ -283,7 +283,7 @@ sub output_requests : Private {
my $display_photos = $c->cobrand->allow_photo_display;
if ($display_photos && $problem->photo) {
my $url = $c->cobrand->base_url();
- my $imgurl = $url . "/photo?id=$id";
+ my $imgurl = $url . "/photo/$id.full.jpeg";
$request->{'media_url'} = [ $imgurl ];
}
push(@problemlist, $request);
diff --git a/perllib/FixMyStreet/App/Controller/Photo.pm b/perllib/FixMyStreet/App/Controller/Photo.pm
index 3f55e4692..3ca7f13a9 100644
--- a/perllib/FixMyStreet/App/Controller/Photo.pm
+++ b/perllib/FixMyStreet/App/Controller/Photo.pm
@@ -5,6 +5,7 @@ use namespace::autoclean;
BEGIN {extends 'Catalyst::Controller'; }
use DateTime::Format::HTTP;
+use Path::Class;
=head1 NAME
@@ -25,17 +26,30 @@ Display a photo
=cut
-sub index :Path :Args(0) {
+sub during :LocalRegex('^([0-9a-f]{40})\.temp\.jpeg$') {
my ( $self, $c ) = @_;
+ my ( $hash ) = @{ $c->req->captures };
- my $id = $c->req->param('id');
- my $comment = $c->req->param('c');
- $c->detach( 'no_photo' ) unless $id || $comment;
+ my $file = file( $c->config->{UPLOAD_DIR}, "$hash.jpeg" );
+ my $photo = $file->slurp;
+
+ if ( $c->cobrand->default_photo_resize ) {
+ $photo = _shrink( $photo, $c->cobrand->default_photo_resize );
+ } else {
+ $photo = _shrink( $photo, 'x250' );
+ }
+
+ $c->forward( 'output', [ $photo ] );
+}
+
+sub index :LocalRegex('^(c/)?(\d+)(?:\.(full|tn|fp))?\.jpeg$') {
+ my ( $self, $c ) = @_;
+ my ( $is_update, $id, $size ) = @{ $c->req->captures };
my @photo;
- if ( $comment ) {
+ if ( $is_update ) {
@photo = $c->model('DB::Comment')->search( {
- id => $comment,
+ id => $id,
state => 'confirmed',
photo => { '!=', undef },
} );
@@ -56,14 +70,30 @@ sub index :Path :Args(0) {
$c->detach( 'no_photo' ) unless @photo;
my $photo = $photo[0]->photo;
- if ( $c->req->param('tn' ) ) {
+
+ # If photo field contains a hash
+ if (length($photo) == 40) {
+ my $file = file( $c->config->{UPLOAD_DIR}, "$photo.jpeg" );
+ $photo = $file->slurp;
+ }
+
+ if ( $size eq 'tn' ) {
$photo = _shrink( $photo, 'x100' );
- } elsif ( $c->req->param('fp' ) ) {
+ } elsif ( $size eq 'fp' ) {
$photo = _crop( $photo );
+ } elsif ( $size eq 'full' ) {
} elsif ( $c->cobrand->default_photo_resize ) {
$photo = _shrink( $photo, $c->cobrand->default_photo_resize );
+ } else {
+ $photo = _shrink( $photo, 'x250' );
}
+ $c->forward( 'output', [ $photo ] );
+}
+
+sub output : Private {
+ my ( $self, $c, $photo ) = @_;
+
my $dt = DateTime->now();
$dt->set_year( $dt->year + 1 );
diff --git a/perllib/FixMyStreet/App/Controller/Questionnaire.pm b/perllib/FixMyStreet/App/Controller/Questionnaire.pm
index f0cb02115..6ed7ddd9d 100755
--- a/perllib/FixMyStreet/App/Controller/Questionnaire.pm
+++ b/perllib/FixMyStreet/App/Controller/Questionnaire.pm
@@ -205,10 +205,7 @@ sub submit_standard : Private {
}
);
if ( my $fileid = $c->stash->{upload_fileid} ) {
- my $file = file( $c->config->{UPLOAD_CACHE}, "$fileid.jpg" );
- my $blob = $file->slurp;
- $file->remove;
- $update->photo($blob);
+ $update->photo( $fileid );
}
$update->insert;
}
diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm
index 12b48a99b..c61f4847c 100644
--- a/perllib/FixMyStreet/App/Controller/Report/New.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/New.pm
@@ -5,6 +5,7 @@ use namespace::autoclean;
BEGIN { extends 'Catalyst::Controller'; }
use FixMyStreet::Geocode;
+use Digest::SHA1 qw(sha1_hex);
use Encode;
use Image::Magick;
use List::MoreUtils qw(uniq);
@@ -47,7 +48,10 @@ back into lat/lng by the map code.
=head2 image related
-Parameters are 'photo' or 'upload_fileid'. The 'photo' is used when a user has selected a file. Once it has been uploaded it is cached on disk so that if there are errors on the form it need not be uploaded again. The cache location is stored in 'upload_fileid'.
+Parameters are 'photo' or 'upload_fileid'. The 'photo' is used when a user has
+selected a file. Once it has been uploaded it is cached on disk so that if
+there are errors on the form it need not be uploaded again. The hash of the
+photo is stored in 'upload_fileid'.
=head2 optional
@@ -200,8 +204,8 @@ sub report_import : Path('/import') {
}
# handle the photo upload
- $c->forward( 'process_photo_upload', [ { rotate_photo => 1 } ] );
- my $photo = $c->stash->{upload_fileid};
+ $c->forward( 'process_photo_upload' );
+ my $fileid = $c->stash->{upload_fileid};
if ( my $error = $c->stash->{photo_error} ) {
push @errors, $error;
}
@@ -224,7 +228,7 @@ sub report_import : Path('/import') {
if $@;
}
- unless ( $photo || ( $latitude || $longitude ) ) {
+ unless ( $fileid || ( $latitude || $longitude ) ) {
push @errors, 'Either a location or a photo must be provided.';
}
@@ -292,11 +296,8 @@ sub report_import : Path('/import') {
);
# If there was a photo add that too
- if ( $photo ) {
- my $file = file( $c->config->{UPLOAD_CACHE}, "$photo.jpg" );
- my $blob = $file->slurp;
- $file->remove;
- $report->photo($blob);
+ if ( $fileid ) {
+ $report->photo($fileid);
}
# save the report;
@@ -825,11 +826,7 @@ sub process_photo : Private {
}
sub process_photo_upload : Private {
- my ( $self, $c, $args ) = @_;
-
- # setup args and set defaults
- $args ||= {};
- $args->{rotate_photo} ||= 0;
+ my ( $self, $c ) = @_;
# check for upload or return
my $upload = $c->req->upload('photo')
@@ -842,9 +839,13 @@ sub process_photo_upload : Private {
return;
}
- # convert the photo into a blob (also resize etc)
- my $photo_blob =
- eval { _process_photo( $upload->fh, $args->{rotate_photo} ) };
+ # get the photo into a variable
+ my $photo_blob = eval {
+ my $filename = $upload->tempname;
+ my $out = `jhead -se -autorot $filename`;
+ my $photo = $upload->slurp;
+ return $photo;
+ };
if ( my $error = $@ ) {
my $format = _(
"That image doesn't appear to have uploaded correctly (%s), please try again."
@@ -853,21 +854,18 @@ sub process_photo_upload : Private {
return;
}
- # we have an image we can use - save it to the cache in case there is an
- # error
- my $cache_dir = dir( $c->config->{UPLOAD_CACHE} );
+ # we have an image we can use - save it to the upload dir for storage
+ my $cache_dir = dir( $c->config->{UPLOAD_DIR} );
$cache_dir->mkpath;
unless ( -d $cache_dir && -w $cache_dir ) {
warn "Can't find/write to photo cache directory '$cache_dir'";
return;
}
- # create a random name and store the file there
- my $fileid = int rand 1_000_000_000;
- my $file = $cache_dir->file("$fileid.jpg");
- $file->openw->print($photo_blob);
+ my $fileid = sha1_hex($photo_blob);
+ $upload->copy_to( file($cache_dir, $fileid . '.jpeg') );
- # stick the random number on the stash
+ # stick the hash on the stash, so don't have to reupload in case of error
$c->stash->{upload_fileid} = $fileid;
return 1;
@@ -883,12 +881,12 @@ does return true and put fileid on stash, otherwise false.
sub process_photo_cache : Private {
my ( $self, $c ) = @_;
- # get the fileid and make sure it is just a number
+ # get the fileid and make sure it is just a hex number
my $fileid = $c->req->param('upload_fileid') || '';
- $fileid =~ s{\D+}{}g;
+ $fileid =~ s{[^0-9a-f]}{}gi;
return unless $fileid;
- my $file = file( $c->config->{UPLOAD_CACHE}, "$fileid.jpg" );
+ my $file = file( $c->config->{UPLOAD_DIR}, "$fileid.jpeg" );
return unless -e $file;
$c->stash->{upload_fileid} = $fileid;
@@ -980,10 +978,7 @@ sub save_user_and_report : Private {
# If there was a photo add that too
if ( my $fileid = $c->stash->{upload_fileid} ) {
- my $file = file( $c->config->{UPLOAD_CACHE}, "$fileid.jpg" );
- my $blob = $file->slurp;
- $file->remove;
- $report->photo($blob);
+ $report->photo($fileid);
}
# Set a default if possible
@@ -1123,41 +1118,6 @@ sub redirect_to_around : Private {
return $c->res->redirect($around_uri);
}
-sub _process_photo {
- my $fh = shift;
- my $import = shift;
-
- my $blob = join('', <$fh>);
- close $fh;
- my ($handle, $filename) = mySociety::TempFiles::named_tempfile('.jpeg');
- print $handle $blob;
- close $handle;
-
- my $photo = Image::Magick->new;
- my $err = $photo->Read($filename);
- unlink $filename;
- throw Error::Simple("read failed: $err") if "$err";
- $err = $photo->Scale(geometry => "250x250>");
- throw Error::Simple("resize failed: $err") if "$err";
- my @blobs = $photo->ImageToBlob();
- undef $photo;
- $photo = $blobs[0];
- return $photo unless $import; # Only check orientation for iPhone imports at present
-
- # Now check if it needs orientating
- ($fh, $filename) = mySociety::TempFiles::named_tempfile('.jpeg');
- print $fh $photo;
- close $fh;
- my $out = `jhead -se -autorot $filename`;
- if ($out) {
- open(FP, $filename) or throw Error::Simple($!);
- $photo = join('', <FP>);
- close FP;
- }
- unlink $filename;
- return $photo;
-}
-
__PACKAGE__->meta->make_immutable;
1;
diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm
index 29933e2f6..600684a40 100644
--- a/perllib/FixMyStreet/App/Controller/Report/Update.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm
@@ -282,10 +282,7 @@ sub save_update : Private {
# If there was a photo add that too
if ( my $fileid = $c->stash->{upload_fileid} ) {
- my $file = file( $c->config->{UPLOAD_CACHE}, "$fileid.jpg" );
- my $blob = $file->slurp;
- $file->remove;
- $update->photo($blob);
+ $update->photo($fileid);
}
if ( $update->in_storage ) {
diff --git a/perllib/FixMyStreet/App/Controller/Rss.pm b/perllib/FixMyStreet/App/Controller/Rss.pm
index 822780b81..4d0b6cb93 100755
--- a/perllib/FixMyStreet/App/Controller/Rss.pm
+++ b/perllib/FixMyStreet/App/Controller/Rss.pm
@@ -267,8 +267,8 @@ sub add_row : Private {
$item{category} = $row->{category} if $row->{category};
if ($c->cobrand->allow_photo_display && $row->{photo}) {
- my $key = $alert_type->item_table eq 'comment' ? 'c' : 'id';
- $item{description} .= ent("\n<br><img src=\"". $c->cobrand->base_url . "/photo?$key=$row->{id}\">");
+ my $key = $alert_type->item_table eq 'comment' ? 'c/' : '';
+ $item{description} .= ent("\n<br><img src=\"". $c->cobrand->base_url . "/photo/$key$row->{id}.jpeg\">");
}
if ( $row->{used_map} ) {
diff --git a/perllib/FixMyStreet/DB/Result/Comment.pm b/perllib/FixMyStreet/DB/Result/Comment.pm
index 958194eb8..195fe4019 100644
--- a/perllib/FixMyStreet/DB/Result/Comment.pm
+++ b/perllib/FixMyStreet/DB/Result/Comment.pm
@@ -132,21 +132,12 @@ sub confirm {
=head2 get_photo_params
Returns a hashref of details of any attached photo for use in templates.
-Hashref contains height, width and url keys.
=cut
sub get_photo_params {
my $self = shift;
-
- return {} unless $self->photo;
-
- my $photo = {};
- ( $photo->{width}, $photo->{height} ) =
- Image::Size::imgsize( \$self->photo );
- $photo->{url} = '/photo?c=' . $self->id;
-
- return $photo;
+ return FixMyStreet::App::get_photo_params($self, 'c');
}
=head2 meta_problem_state
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index d0867c5ca..ce7488703 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -400,21 +400,12 @@ sub url {
=head2 get_photo_params
Returns a hashref of details of any attached photo for use in templates.
-Hashref contains height, width and url keys.
=cut
sub get_photo_params {
my $self = shift;
-
- return {} unless $self->photo;
-
- my $photo = {};
- ( $photo->{width}, $photo->{height} ) =
- Image::Size::imgsize( \$self->photo );
- $photo->{url} = '/photo?id=' . $self->id;
-
- return $photo;
+ return FixMyStreet::App::get_photo_params($self, 'id');
}
=head2 is_open