Using Paperclip and Amazon S3 for zip file containing photos
I currently have a working photo uploader that creates Photo images using paperclip and aws-s3 gems. The loader can also dynamically add Photo upload fields so multiple files can be uploaded at once on a single submit. What I'd like to do is have the option of uploading a zip file with the expectation that the file contains Photos and have it run through my same process of creating thumbnails, medium size, and original images开发者_JS百科 that the single photo file upload goes through. My model and controller is pretty straight forward with storing photos locally if on development, or on s3 if production, with just a little bit on fanciness with the view template:
photo.rb
class Photo < ActiveRecord::Base
belongs_to :album
if AppConfig['s3']
has_attached_file :data,
:styles => {
:thumb => "100x100>",
:medium => "500x500>"
},
:storage => :s3,
:default_style => :original,
:bucket => AppConfig['s3']['bucket_name'],
:s3_credentials => { :access_key_id => AppConfig['s3']['access_id'], :secret_access_key => AppConfig['s3']['secret_key'] },
:s3_headers => { 'Cache-Control' => 'max-age=315576000', 'Expires' => 10.years.from_now.httpdate },
:path => "/:class/:id/:style/:filename"
else
has_attached_file :data,
:styles => {
:thumb => "100x100>",
:medium => "500x500>"
},
:storage => :filesystem,
:default_style => :original
end
end
*photos_controller.rb*
class Admin::PhotosController < Admin::AdminController
def index
@photos = Photo.all
end
def show
@photo = Photo.find(params[:id])
end
def new
@photo = Photo.new
end
def create
@photo = Photo.new(params[:photo])
if @photo.save
flash[:notice] = "Successfully created photo."
redirect_to [:admin, @photo]
else
render :action => 'new'
end
end
def edit
@photo = Photo.find(params[:id])
end
def update
@photo = Photo.find(params[:id])
album = @photo.album
if @photo.update_attributes(params[:photo])
flash[:notice] = "Successfully updated photo."
redirect_to [:admin, @photo]
else
redirect_to edit_admin_album_url(album)
end
end
def destroy
@photo = Photo.find(params[:id])
album = @photo.album
@photo.destroy
flash[:notice] = "Successfully destroyed photo."
redirect_to edit_admin_album_url(album)
end
end
The interesting parts of the view are here:
*_form.html.haml*
#photos
- if @album.new_record?
= render :partial => 'photo', :locals => { :form => f, :photo => @album.photos.build }
- else
- for photo in @album.photos
.photo
= link_to(image_tag(photo.data(:thumb)), photo.data(:medium), :class => 'photo_link')
- f.fields_for @album.photos do |photo_field|
/ Viewable?
/ = photo_field.check_box :viewable
%br
= link_to "Delete", [:admin, photo], :confirm => 'Are you sure?', :method => :delete
.float_clear
= add_object_link("New Photo", f, @album.photos.build, "photo", "#photos")
.row
= submit_tag "Save", :disable_with => "Uploading please wait..."
.float_clear
*_photo.html.haml*
.photo_form
%p
- form.fields_for :photos, photo, :child_index => (photo.new_record? ? "index_to_replace_with_js" : nil) do |photo_form|
= photo_form.file_field :data
= link_to_function "delete", "remove_field($(this), ('.photo_form'))"
%br
Welcome all ideas or contributions! Thanks!
I would use a callback to pull out the archive files (zip, tar etc) and let the image files go on through to be processed/saved. Use delayed_job to process the archives after upload to increase the user experience and ease the load on your server.
I'm not sure of any archive utility wrappers in ruby but you could use system calls to unzip archives using tar or something similar, then loop through the unzipped files to process and store the images and discard non-image files.
You could even use a rake task and cron job to periodically unzip, loop through and create Photos from the untarred archives.
精彩评论