画像掲示板(Mojolicious::Liteバージョン)
画像掲示板です。これはかんたんプログラミング CGI/Perl」の第5章の2節の「画像掲示板」をMojolicious::Liteを使って書き直したものになっています。
画像掲示板
画像掲示板です。
[f:id:yukikimoto:20100219230544p:image]
ソースコード
画像掲示板のソースコードです。
use Mojolicious::Lite; use File::Basename 'basename'; use File::Path 'mkpath'; # Image base URL my $IMAGE_BASE = '/image-bbs/image'; # Directory to save image files # (app is Mojolicious object. static is MojoX::Dispatcher::Static object) my $IMAGE_DIR = app->home->rel_file('/public') . $IMAGE_BASE; # Create directory if not exists unless (-d $IMAGE_DIR) { mkpath $IMAGE_DIR or die "Cannot create dirctory: $IMAGE_DIR"; } # Display top page get '/' => sub { my $self = shift; # Get file names(Only base name) my @images = map {basename($_)} glob("$IMAGE_DIR/*"); # Sort by new order @images = sort {$b cmp $a} @images; # Render return $self->render(images => \@images, image_base => $IMAGE_BASE); } => 'index'; # Upload image file post '/upload' => sub { my $self = shift; # Uploaded image(Mojo::Upload object) my $image = $self->req->upload('image'); # Not upload unless ($image) { return $self->render( template => 'error', message => "Upload fail. File is not specified." ); } # Upload max size my $upload_max_size = 3 * 1024 * 1024; # Over max size if ($image->size > $upload_max_size) { return $self->render( template => 'error', message => "Upload fail. Image size is too large." ); } # Check file type my $image_type = $image->headers->content_type; my %valid_types = map {$_ => 1} qw(image/gif image/jpeg image/png); # Content type is wrong unless ($valid_types{$image_type}) { return $self->render( template => 'error', message => "Upload fail. Content type is wrong." ); } # Extention my $exts = {'image/gif' => 'gif', 'image/jpeg' => 'jpg', 'image/png' => 'png'}; my $ext = $exts->{$image_type}; # Image file my $image_file = "$IMAGE_DIR/" . create_filename(). ".$ext"; # If file is exists, Retry creating filename while(-f $image_file){ $image_file = "$IMAGE_DIR/" . create_filename() . ".$ext"; } # Save to file $image->move_to($image_file); # Redirect to top page $self->redirect_to('index'); } => 'upload'; sub create_filename { # Date and time my ($sec, $min, $hour, $mday, $month, $year) = localtime; $month = $month + 1; $year = $year + 1900; # Random number(0 ~ 99999) my $rand_num = int(rand 100000); # Create file name form datatime and random number # (like image-20091014051023-78973) my $name = sprintf( "image-%04s%02s%02s%02s%02s%02s-%05s", $year, $month, $mday, $hour, $min, $sec, $rand_num ); return $name; } app->start; __DATA__ @@ error.html.ep <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" > <title>Error</title> </head> <body> <%= $message %> </body> </html> @@ index.html.ep <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" > <title>Image BBS</title> </head> <body> <h1>Image BBS</h1> <form method="post" action="<%= url_for('upload') %>" enctype ="multipart/form-data"> <div> File name <input type="file" name="image" > <input type="submit" value="Upload" > </div> </form> <div> <% for my $image (@$images) { %> <div> <hr> <div>Image: <%= $image %></div> <div> <img src="<%= "$image_base/$image" %>"> </div> <div> <% } %> </div> </body> </html>
(参考)File::Path
while文は、画像ファイルが存在した場合に、違うファイル名を作成するのに利用されています。