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ć 
[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. ![]()
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/