Obsługa spakowanych plików

Witam.
Chciałbym zrobić coś w tym guście:
Ładowanie spakowanego pliku (docelowo katalog ze zdjęciami), automatyczne rozpakowanie i zapisanie poszczególnych elementów.
Czy da się to zrobić? Lub może jest inny prostszy sposób na załadowanie wielu plików (obrazków) przy wykonaniu jednej akcji z poziomu użytkownika?

Mam coś takiego napisane. Do tej aplikacji używałem pluginu file_column, dlatego w pewnym miejscu używam klasy LocalUploadedFile - zachowuje się jak uploadowany plik. Image to model railsowy korzystający z file_column.

Bez żadnych zmian pewnie nie zadziała u Ciebie w aplikacji, ale możesz się na tym wzorować :slight_smile:

[code] require ‘zip/zip’
require ‘zip/zipfilesystem’
require ‘tempfile’
require ‘local_uploaded_file’

def add_to_gallery(uploaded_file, gallery)
if uploaded_file.content_type =~ /application/(zip|x-zip-compressed)/
files = []
Zip::ZipInputStream::open(uploaded_file.path) do |zipfile|
while zip_entry = zipfile.get_next_entry
files << zip_entry.to_s unless zip_entry.directory?
end
end

  Zip::ZipFile.open(uploaded_file.path) do |zipfile|
    files.each do |f|
      if zipfile.file.file?(f)
        temp = Tempfile.new(File.basename(f))
        local_file = LocalUploadedFile.new(temp.path, "image/jpeg")

        local_file.write(zipfile.file.read(f))

        image = Image.new(:file => local_file)
        image.gallery = gallery
        image.save
      end
    end
  end
elsif uploaded_file.content_type =~ /image\/jpeg/
  temp = Tempfile.new(File.basename(uploaded_file.original_filename))
  local_file = LocalUploadedFile.new(temp.path, "image/jpeg")

  local_file.write(uploaded_file.read)

  image = Image.new(:file => local_file)
  image.gallery = gallery
  image.save
end

end[/code]
i LocalUploadedFile:

[code] require ‘tempfile’
class LocalUploadedFile
attr_reader :original_filename
attr_reader :content_type

def initialize(path, content_type = 'text/plain')
  raise "#{path} file does not exist" unless File.exist?(path)
  @content_type = content_type
  @original_filename = File.basename(path)
  @tempfile = Tempfile.new(@original_filename)
  FileUtils.copy_file(path, @tempfile.path)
end

def path #:nodoc:
  @tempfile.path
end

alias local_path path

def method_missing(method_name, *args, &block) #:nodoc:
  @tempfile.send(method_name, *args, &block)
end

end[/code]

Teraz mam mały problem - obsługa działa ale tylko na kompie, na którym stoi serwer.
Czy problem tkwi w tym że nie korzystam z TempFile?

def upload_dir(file) require 'zip/zip' require 'zip/zipfilesystem' dir_name=file.original_filename.gsub(/.zip/,'') if file.content_type =~ /application\/(zip|x-zip-compressed)/ Dir.mkdir("public/images/photo/#{dir_name}") files = [] Zip::ZipInputStream::open(file.path) do |zipfile| while zip_entry = zipfile.get_next_entry files << zip_entry.to_s unless zip_entry.directory? end end end Zip::ZipFile.open(file.path) do |zipfile| files.each do |f| if zipfile.file.file?(f) File.open("public/images/photo/#{dir_name}/#{f}", "wb") do |ff| ff.write(zipfile.file.read(f)) end end end end end

Nie mam pojęcia. :slight_smile:
Sypnij jakimś komunikatem błędu, opisz co się dzieje, alboco.

Chyba już wiem gdzie jest problem, ale nie rozumiem go ani trochę.
Testowałem na 3 kompach ten sam spakowany plik. W kodzie używam metody .content_type i za każdym razem wynik był inny:
u mnie: application/x-zip-compressed
u kumpla: application/zip
u drugiego kumpla: application/force-download

hmm… w takim wypadku najlepiej próbować obczaić po rozszerzeniu.

Coś takiego zamiast tego ifa sprawdzającego content_type:

if file.original_filename =~ /\.zip$/i

Co do rozpoznawanego content type to mogę od siebie powiedzieć, że miałem coś podobnego jakiś czas temu w aplikacji php. Na dwóch różnych maszynach dostawałem różne wartości dla content-type. Doszedłem do tego, że prawdopodobnie wynika to z różnych plików /etc/mime.types. Prawdopodobnie tutaj jest taka sama sytuacja.

content-type uploadowanego pliku jest ustawiany w zależności od systemu operacyjnego i przeglądarki. Np. IE 6 ustawia image/pjpeg a nie image/jpeg - trzeba na to zwrócić uwagę.

Jest jeszcze mimetype_fu: http://code.google.com/p/mimetype-fu/