2010-02-09 7 views
18

Вы знаете, что на некоторых сайтах, когда вас просят загрузить, скажем, аватар, вы нажимаете на кнопку, выбираете свой файл, а затем нажимаете «ОК», но до вы отправляете страницу (как и в, никакая запись не создается/updated), появляется небольшой предварительный просмотр изображения?Rails: Paperclip & previews?

Как бы это сделать, используя Paperclip для Rails?

Бонусные баллы для всех, кто может указать мне на учебник или что-то, что может сказать мне, как сделать обрезку Javascript на изображении перед сохранением записи.

Я не смог найти много на Google по этому вопросу ... спасибо за помощь!

ответ

19

Этот вид проблемы проблематичен с точки зрения Rails из-за способа загрузки изображений. Одна из стратегий, чтобы заставить его работать лучше:

  • сделать вложенную форму для загрузки изображений, возможно, с использованием swfupload, чтобы сделать его более обтекаемым.
  • Создайте модель для получения ваших загрузок, которая включает в себя некоторый рандомизированный ключ доступа, используемый для извлечения и связывания. Скрепка обрабатывает прикрепленный файл.
  • Используйте AJAX, чтобы заполнить свою основную форму, вставив скрытое поле или потенциально видимый элемент check-box с соответствующей уникальной_key, когда заканчивается подформат.

Типичная модель выглядит примерно так:

class Avatar < ActiveRecord::Base 
    has_attached_file :image 
    # ... Additional Paperclip options here 

    before_validation :assign_unique_key 

    belongs_to :user 

    def to_param 
    self.unique_key 
    end 

protected 
    def assign_unique_key 
    return if (self.unique_key.present?) 

    self.unique_key = Digest::SHA1.hexdigest(ActiveSupport::SecureRandom.random_number(1<<512).to_s) 
    end 
end 

Причина unique_key поля, так что вы можете связать это в форму потенциально неспасенной запись. Преимущественно использовать unique_key вместо id при размещении в URL-адресах, поскольку трудно определить, должен ли пользователь видеть это изображение или нет, когда он загружен, поскольку пользователь-владелец еще не может быть назначен.

Это также мешает любопытным людям изменять какой-либо последовательный, легко угаданный идентификатор в вашем URL-адресе и видеть другие загруженные аватары.

Вы можете получить окончательный URL-адрес уменьшенного изображения для Аватара, как и любой модели на данный момент.

Вы можете легко вырезать параметры при получении и перевести обратно на Avatar ID номеров:

# If an avatar_id parameter has been assigned... 
if (params[:user][:avatar_id]) 
    # ...resolve this as if it were a unique_key value... 
    avatar = Avatar.find_by_unique_key(params[:user][:avatar_id]) 
    # ...and repopulate the parameters if it has been found. 
    params[:user][:avatar_id] = (avatar && avatar.id) 
end 

# ... params[:user] used as required for create or update 

Как люди загружать и повторно загружать-изображения, вы в конечном итоге имеют большое количество потерянных записей, которые не являются фактически используется везде. Просто написать задачу рейка, чтобы очистить все это после того, как прошло разумное количество времени. Например:

task :purge_orphan_avatars => :environment do 
    # Clear out any Avatar records that have not been assigned to a particular 
    # user within the span of two days. 
    Avatar.destroy_all([ 'created_at<? AND user_id IS NULL', 2.days.ago ]) 
end 

Использование destroy_all должны иметь эффект очистки всех Paperclip материала, а также.

5

Я нашел решение отправил here полезно, вам просто нужно изменить его, чтобы быть только один файл (если вы делаете одного загрузки файла):

<%= image_tag @upload.image, id:"something_unique"%> 
<div class="row"> 
    <%= form_for @upload, :html => { :multipart => true } do |f| %> 
    <%= f.file_field :image, id:"something_else_unique" %> 
    <%= f.submit "Add photo" %> 
    <% end %> 
</div> 

<script> 
    function handleFileSelect(evt) { 
    var files = evt.target.files; // FileList object 
     f=files[0] 
     // Only process image files. 
     if (f.type.match('image.*')) { 
     var reader = new FileReader(); 
     reader.onload = (function(theFile) { 
      return function(e) { 
      // alert(e.target.result); 
      document.getElementById("something_unique").src=e.target.result; 
      }; 
     })(f); 

     // Read in the image file as a data URL. 
     reader.readAsDataURL(f); 
     } 
    } 
    document.getElementById('something_else_unique').addEventListener('change', handleFileSelect, false); 
</script> 

Примечание: Я использовал отдельную модель для скрепки, модель загрузки с атрибутом изображения. Вы можете добавить стиль в тег предварительного просмотра изображения, чтобы отформатировать размер изображения (в противном случае это будет оригинальный размер).