Oct 30 2011
Upload de múltiplas fotos com Paperclip + Uploadify
Eu já fiz um post sobre como fazer upload de fotos usando Paperclip. Agora, vou mostrar como fazer vários uploads de uma vez só usando Paperclip + Uploadify.
Para esse exemplo, vamos considerar que um álbum possui várias fotos.
Comece adicionando a gem do Paperclip.
#Gemfile gem 'paperclip'
Rode o bundle install para instalar a gem.
Gem adicionada, vamos criar nosso album.
rails g scaffold album name:string
Agora, vamos fazer um scaffold para as fotos.
rails g scaffold photo album_id:integer
Para facilitar, iremos apenas adicionar o album_id e, para adicionar os outros campos necessários para o paperclip, vamos usar o gerador que ele disponibiliza.
rails generate paperclip Photo image
Usaremos o rake db:migrate para atualizar o banco:
rake db:migrate
Precisamos, agora, alterar nossos models para criar os relacionamentos e adicionar o helper do paperclip.
#app/models/album.rb class Album < ActiveRecord::Base has_many :photos end
#app/models/photo.rb class Photo < ActiveRecord::Base belongs_to :album has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" } end
Até aqui, nada diferente do que já estamos acostumados. Agora, vem a parte dos múltiplos uploads. Para começar, adicionaremos o form que irá adicionar as fotos.
#app/views/albums/show.html.erb <%= form_for(Photo.new(:album_id => @album.id)) do |f| %> <%= f.hidden_field :album_id, "value" => @album.id %> <p><%= f.file_field :image %></p> <% end %>
Agora, temos o nosso formulário, mas ele não faz nada por enquanto; ainda não tem nenhum botão para enviar. Para que o Uploadify funcione, precisamos, ainda, adicionar algumas coisas. Primeiro, vamos alterar o application.html.erb.
#app/views/layouts/application.html.erb
<head>
<%= yield(:head) %>
</head>Estamos adicionando esse yield(:head) porque só adicionaremos o javascript do uploadify no arquivo que irá utilizá-lo. Vamos a esse arquivo, então. Editaremos, novamente, o show do usuário e adicionaremos o seguinte código no inicio do arquivo.
#app/views/albums/show.html.erb <% content_for(:head) do %> <%= render :partial => "upload" %> <% end %>
Como vocês podem ver, estamos adicionando um partial upload; ele conterá o código javascript do Uploadify.
#app/views/albums/_upload.html.erb <script type="text/javascript" charset="utf-8"> <%- session_key = Rails.application.config.session_options[:key] -%> $(document).ready(function() { $('#photo_image').click(function(event){ event.preventDefault(); }); $('#photo_image').uploadify({ uploader : '/assets/uploadify.swf', cancelImg : '/assets/cancel.png', multi : true, auto : true, script : '/photos', scriptData : { '_http_accept': 'application/javascript', 'format' : 'json', '_method': 'post', 'album_id' : '<%= @album.id %>', '<%= session_key %>' : encodeURIComponent('<%= u cookies[session_key] %>'), 'authenticity_token': encodeURIComponent('<%= u form_authenticity_token %>') }, onComplete : function(event, queueID, fileObj, response, data) { $('.thumbs').fadeOut('slow').load('/albums/<%= @album.id %> .thumbs').fadeIn("slow"); } }); }); </script>
O Uploadify utiliza um arquivo flash para funcionar e, para que sua aplicação funcione direito com isso, precisamos adicionar um token de autenticidade para o flash; são essas 3 linhas:
<%- session_key = Rails.application.config.session_options[:key] -%> '<%= session_key %>' : encodeURIComponent('<%= u cookies[session_key] %>'), 'authenticity_token': encodeURIComponent('<%= u form_authenticity_token %>')
Vamos, também, adicionar um novo arquivo com o seguinte conteúdo:
#app/middleware/flash_session_cookie_middleware.rb require 'rack/utils' class FlashSessionCookieMiddleware def initialize(app, session_key = '_session_id') @app = app @session_key = session_key end def call(env) if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/ req = Rack::Request.new(env) env['HTTP_COOKIE'] = [ @session_key, req.params[@session_key] ].join('=').freeze unless req.params[@session_key].nil? env['HTTP_ACCEPT'] = "#{req.params['_http_accept']}".freeze unless req.params['_http_accept'].nil? end @app.call(env) end end
Agora, faremos com que o rails adicione isso na nossa sessão. Adicione o código abaixo no arquivo session_store.rb
#config/initializers/session_store.rb ... Rails.application.config.middleware.insert_before( ActionDispatch::Session::CookieStore, FlashSessionCookieMiddleware, Rails.application.config.session_options[:key] )
A parte do Uploadify nas views está pronta. O próximo passo é adicionar as imagens na tela. Para isso, editaremos o arquivo show, novamente.
#app/views/albums/show.html.erb
<div class="thumbs">
<% @album.photos.each do |photo| %>
<p><%= image_tag photo.image.url(:medium) %></p>
<% end %>
</div>Com os Models e views prontos, precisamos adicionar códigos no controller, também, e alterar o método create para receber os novos parâmetros enviados pelo form do Uploadify.
Primeiro, criaremos um método privado com o seguinte código:
#app/controllers/photos_controller.rb private def coerce(params) if params[:photo].nil? h = Hash.new h[:photo] = Hash.new h[:photo][:album_id] = params[:album_id] h[:photo][:image] = params[:Filedata] h[:photo][:image].content_type = MIME::Types.type_for(h[:photo][:image].original_filename).to_s h else params end end
Ele vai tratar os parâmetos enviados e fazer com que fiquem em um formato que podemos usar para salvar nosso objeto. Também precisamos alterar o método create dessa forma:
#app/controllers/photos_controller.rb def create @album = Album.find(params[:album_id]) newparams = coerce(params) @photo = Photo.new(newparams[:photo]) respond_to do |format| if @photo.save format.html { redirect_to album_path(@album) } format.json { render :json => { :result => ‘success’, :upload => photo_path(@photo) } } else format.html { render :action => “new” } end end end
Para finalizar, adicionaremos os arquivos do Uploadify na nossa aplicação. Ficará da seguinte forma:
#app/assets/javascripts jquery.uploadify.v2.1.4.min.js swfobject.js
#app/assets/stylesheets uploadify.css
#app/assets/swf uploadify.swf
Todos esses arquivos do Uploadify você encontra no zip, disponibilizado no site do plugin. Para baixar direto, clique aqui.
Acesse http://localhost:3000/albums e crie um álbum e, depois disso, teste o upload das fotos.
Você pode baixar o código fonte do exemplo no repositório blog-posts, no Github.
Nov 12, 2011 @ 13:23:00
bem legal esse post, irei tentar fazer o mesmo depois .