carrierwaveuploader / carrierwave

Classier solution for file uploads for Rails, Sinatra and other Ruby web frameworks
https://github.com/carrierwaveuploader/carrierwave
8.78k stars 1.66k forks source link

Files not automatically deleted after upgrading to 3.0 #2716

Closed simptive closed 10 months ago

simptive commented 11 months ago

I was using carrierwave 2.2.0 in rails 7.1.1. When a file is replaced or deleted, corresponding file was also overwrite / deleted from the disk. After migrating to 3.0, old files are kept on disk no matter file was deleted (params {:file => nil}) or replaced with other file by the user. I suspect from the documentation that carrierwave will no longer be deleting files and rather promoting explicit destroy method but it's not clear from the documentation. Please clear if you have insights.

mshibuya commented 10 months ago

Please provide more details, like your uploader and related implementation. Obviously a deleted file is expected to be removed from the disk, so it'll be a bug in your app or possibly CarrierWave.

simptive commented 10 months ago

My implementation is a bit complex but I hope you'll get it. Here's my photograph_uploader.rb:

class HRM::PhotographUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  storage :file

  before :process, :validate

  process resize_to_fill: [255,300], convert: :jpg, interlace: :plane

  def store_dir
    "storage/#{model.class.to_s.underscore}/#{mounted_as}"
  end

  def default_url(*args)
    ActionController::Base.helpers.asset_path("user-default.jpg")
  end

  def extension_allowlist
    %w(jpg jpeg png)
  end

  def content_type_allowlist
    [/image\//]
  end

  def validate(file)
    begin
      image = MiniMagick::Image.open(file.path)
    rescue
      raise "Image format isn't valid"
    end
  end

  def filename
    @name ||= "#{Digest::SHA1.hexdigest("#{Time.now.to_i}#{file.original_filename}")}.#{file.extension.downcase}" if original_filename
  end
end

Relevant Model:

class HRM::Employee < HRM::HrmRecord
  mount_uploader :photograph, HRM::PhotographUploader
end

Controller:

class Hrm::EmployeesController < ApplicationController
  before_action -> { set_attachment_params(params[:emp],:photograph) }, only: [:create,:update,:save_photograph]

  def save_photograph
    @emp.update!(photograph: params[:emp][:photograph])
    redirect_back(fallback_location: authenticated_root_path)
  end

  def set_attachment_params(obj_params,attr)
    # '1' mean current attachment should be preserved,
    # '0' mean delete it, otherwise new attachment will be saved.
    return unless obj_params
    if obj_params['0'] # array of objects
      obj_params.each{|i,h| set_attachment_params(h,attr) }
    else
      obj_params.delete(attr) if obj_params[attr] == '1'
    end
  end

end

View:

<%= image_view _class: "photograph editable #{_class}", path: value, width: img_width, height: img_height  do %>
  <%= file_field obj, field, accept: ".png, .jpg, .jpeg" %>
  <%# Current Photo preserved flag. Below element will be deleted if photo is changed. %>
  <%= hidden_field obj, field, value: '1', class: 'preserve-photo' %>
  <%= button_tag type: 'button', class: 'btn btn-danger btn-flat btn-sm remove-photo', data: {avatar: avatar } do %>
    <i class="fa fa-trash"></i>
  <% end %>
  <%= label obj, field, class: 'btn btn-info btn-flat btn-sm' do %>
    <i class="fa fa-folder-open"></i>
  <% end %>
<% end %>
mshibuya commented 10 months ago

The issue you're having could be this one: https://github.com/carrierwaveuploader/carrierwave/issues/2713 Could you try the master branch, as the fix is not released yet?

simptive commented 10 months ago

You're right. Tried master branch (3.0.5 d27c987) and the issue is gone.