简体   繁体   中英

Carrierwave uncompress RAR file after upload

I'm actually looking for advices more than pure coding answers on how to uncompress RAR/ZIP file after upload while keeping a maximum rate of data integrity.

Here is my problem : my application's users are uploading files generated by Adobe Edge (we are using it for animated ads) which are in RAR format. To upload the file, it was really trivial. Here is my uploader :

class MediaUploader < CarrierWave::Uploader::Base
  storage :file

  def store_dir
    "uploads/#{ model.class.to_s.underscore }/#{ mounted_as }/#{ ScatterSwap.hash(model.id) }"
  end

  def extension_white_list
    %w(jpg jpeg gif png rar zip)
  end

  def filename
    "#{ secure_token }.#{ file.extension }" if original_filename.present?
  end

  protected

  def secure_token
    var = :"@#{ mounted_as }_secure_token"
    model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
  end
end

Now, in my case, the RAR file is not actually the one I'll be using. What I need are the files contain inside the archive. Those files generally looks like that :

- edge_includes
|
- images
|
- js
|
| ADS_1234_988x160_edge.js
| ADS_1234_988x160_edgeActions.js
| ADS_1234_988x160.an
| ADS_1234_988x160.html

From the above example, I need to store the reference to ADS_1234_988x160.html file within the database.

For this purpose, I was going to use Carrierwave callbacks in order to :

after :store, :uncompress_and_update_reference

def uncompress_and_update_reference(file)
  # uncompress and update reference
end
  • Uncompress the archive (probably using rubyzip )
  • Get the path to ADS_1234_988x160.html
  • Update the reference inside the database

Is there any better way to handle it? How to handle failure or network errors? Any ideas are welcome.

I had similar problem: zip is uploaded but it should not be stored, only unzipped content. I solved it by implementing dedicated storage. Something like:

class MyStorage
  class App < CarrierWave::Storage::Abstract
    def store!(file)
      # invoked when file is moved from cache into store
      # unzip and update db here
    end

    def retrieve!(identifier)
      MyZipFile.new(identifier)
    end
  end
end

class MyZipFile
  def initialize(identifier)
    @identifier = identifier
  end

  def path
    file.path
  end

  def delete
    # delete unzipped files
  end

  def file
    @file ||= zip_file
  end

  def zip_file
    # create zip file somewhere in tmp dir
  end
end
# in uploader file
storage MyStorage
storage :my_storage

If symbol is used than it need to be defined in carrierwave config:

CarrierWave.configure do |config|
  config.storage_engines.merge!(my_storage: 'MyStorage')
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM