Posts
multiple image upload with preview using ajax and jquery
04 Jul 2010
Tags:
paperclip, preview, ajax, jquery, multiple image upload
In this tutorial, we will use jquery to upload multiple images using ajax and show a preview of the images. We'll also use the paperclip gem to store the files. You can look at how to add paperclip to your project .
First we generate the image model and set it to use paperclip. We'll also create a photo controller
>> script/generate model photo >> script/generate paperclip photo photo >> rake db:migrate >> script/generate controller photos
# app/models/photo.rb class Photo < ActiveRecord::Base has_attached_file :photo end
Next, we setup the view and javascript for ajaxupload.
Again, I'm using haml instead of erb templates, and builder for creating DOM elements.
And since we're using prototype and jquery in the same page, we need to make sure that there's no conflict between the two libraries. Add the following code in the head tag of your page.
= javascript_include_tag :defaults = javascript_include_tag 'builder', 'jquery-1.4.2.min', 'ajaxupload' :javascript var $j = jQuery.noConflict();
And here's the view
# app/views/photos/new.html.haml - form_tag photos_path, :method => :post do #photos #file_upload %label Add a Photo = file_field_tag :photo, '', :id => 'file_tag' = image_tag '/images/spinner.gif', :id => 'spinner', :style => 'display:none' = submit_tag 'Save Photos' :javascript $j(document).ready(function(){ new AjaxUpload('file_tag', { action: '/photo_preview?authenticity_token=' + encodeURIComponent(#{form_authenticity_token.inspect}), name: 'image', onSubmit: function(file, extension) { $('spinner').show(); }, onComplete: function(file, response) { $('spinner').hide(); show_preview(response); } }); }); function show_preview(path) { var parent = Builder.node('div', {class:'preview'}); var image = Builder.node('img', {src:path, width:'80px'}); var hidden = Builder.node('input', {type:'hidden', value:path, name:'photo[]'}); parent.appendChild(image); parent.appendChild(hidden); $('photos').appendChild(parent); }
Now we need to create the photo_preview and create action in photos controller
# app/controllers/photos_controller.rb # of course, this code won't work if the user uploads different photos with the same filename def create photos = params[:paths].collect {|p| {:photo => File.new('public' + p)}} @photos = Photo.create(photos) # now do whatever you wish with @photos end def photo_preview if params[:image] filename = params[:image].original_filename path = '/images/' + filename f = File.new('public' + path, 'w') {|f| f.write params[:image].read} render :text => path end end