2010-02-24 11 views
7

Bir zipoutputstream dizinleri eklemek için rubyzip almakla uğraşıyorum. (Çıkış akımını istiyorum, böylece bir ray denetleyicisinden gönderebilirim).Dosya ve iç içe dizinleri bir zipoutputstream eklemek için rubyzip kullanma

http://info.michael-simons.eu/2008/01/21/using-rubyzip-to-create-zip-files-on-the-fly/

aşağıdaki hatayı alıyorum eklemek için dosyaların listesini dizinleri içerecek şekilde değiştirilmiş:

Herhangi bir yardım büyük takdir Benim kod bu örneği takip eder. http://zipruby.rubyforge.org/:

GÜNCELLEME

çok sayıda çözüm denedikten sonra temiz bir API ve iyi örnekler de var zipruby ile iyi bir başarı elde etti.

+0

Harika bir iş bulmak zipruby, günümü kurtardı! –

cevap

5

OOOOOuuuhh ... DEFINITELY ZIPPY istiyor. Rubyzip'teki karmaşıklığı çok fazla özetleyen bir Rails eklentisi ve (hatırladığımdan) dizinler de dahil olmak üzere, bahsettiğiniz şeyi yaratmanızı sağlar. İşte

gitmek:

http://github.com/toretore/zippy

Ve zippy sitesinden direkt:

Example controller: 
def show 
    @gallery = Gallery.find(params[:id]) 
    respond_to do |format| 
    format.html 
    format.zip 
    end 
end 

Example view: 
zip['description.txt'] = @gallery.description 
@gallery.photos.each do |photo| 
    zip["photo_#{photo.id}.png"] = File.open(photo.url) 
end 

düzenlemek:

Hmm ... Bütün: Kullanıcı comment başına Değişiklik Yapılması Zippy kullanmanın amacı ruby ​​zip kullanmak için çok daha kolay hale getirmektir. Ya

Burada dizinleri ile bir dizin yapmak nasıl ... ikinci (veya ilk) bakmak almak isteyebilirsiniz:

some_var = Zippy.open('awsum.zip') do |zip| 
    %w{dir_a dir_b dir_c diri}.each do |dir| 
    zip["bin/#{dir}/"] 
    end 
end 

... 

send_file some_var, :file_name => ... 
+0

Teşekkürler bu iyi görünüyor, ancak dokümanlar biraz utangaç ve şu an kaynağında delme zamanı yok. Yani, örneğin, bir zip akışı nasıl oluşturabilirim ve bir dizin dizini ekleyebilir miyim? Ayrıca, özel bir mime türü yerine sendfile kullanmalıyım. Teşekkürler. İlgilendiğiniz takdirde – fturtle

+0

cevabı düzeltildi. – btelles

+0

Üzgünüm, ama bu gem oldukça zor bir iş buldum. Yeni oluşturulan bir zip'i istediğim şekilde aktarabileceğim bir kaç tane daha deneyeceğim. – fturtle

9
Zip::ZipFile.open(path, Zip::ZipFile::CREATE) do |zip| 
    songs.each do |song| 
    zip.add "record/#{song.title.parameterize}.mp3", song.file.to_file.path 
    end 
end 
+0

Basit ve çalışıyor – benjineer

3

Zippy bunun için çalışacaktır. Bunu yapmak için daha güzel bir yol olabilir, ancak esasen hiçbir belge olmadığı için, Zetty ile bir Rakefile'da dizinleri yinelemeli olarak kopyalamak için geldim.

C:\> cd my 
C:\my> rake myzip 
: Böyle kullanabilirsiniz Rakefile

Şimdi
#Rakefile 
def add_file(zippyfile, dst_dir, f) 
    zippyfile["#{dst_dir}/#{f}"] = File.open(f) 
end 

def add_dir(zippyfile, dst_dir, d) 
    glob = "#{d}/**/*" 
    FileList.new(glob).each { |f| 
    if (File.file?(f)) 
     add_file zippyfile, dst_dir, f 
    end 
    } 
end 

task :myzip do 
    Zippy.create 'my.zip' do |z| 
    add_dir z, 'my', 'app' 
    add_dir z, 'my', 'config' 
    #... 
    add_file z, 'my', 'config.ru' 
    add_file z, 'my', 'Gemfile' 
    #... 
    end 
end 

#Gemfile 
source 'http://rubygems.org' 
gem 'rails' 
gem 'zippy' 

Ve şudur: Bu Rakefile benim Gemfile içinde mücevher gereksinimlerini koymak böylece Rails ortamında kullanılır

ve my.zip, seçili dosya ve dizinlerin kopyaları ile 'my' adında bir iç dizin içeren üretecek.

2

original article'da kullanılan aynı ZipOutputStream ile çalışan dizinleri alabildim.

Tek yapmam gereken, zos.put_next_entry numaralı telefonu ararken dizini eklemekti.Örneğin

:

require 'zip/zip' 
require 'zip/zipfilesystem' 

t = Tempfile.new("some-weird-temp-file-basename-#{request.remote_ip}") 
# Give the path of the temp file to the zip outputstream, it won't try to open it as an archive. 
Zip::ZipOutputStream.open(t.path) do |zos| 
    some_file_list.each do |file| 
    # Create a new entry with some arbitrary name 
    zos.put_next_entry("myfolder/some-funny-name.jpg") # Added myfolder/ 
    # Add the contents of the file, don't read the stuff linewise if its binary, instead use direct IO 
    zos.print IO.read(file.path) 
    end 
end 
# End of the block automatically closes the file. 
# Send it using the right mime type, with a download window and some nice file name. 
send_file t.path, :type => 'application/zip', :disposition => 'attachment', :filename => "some-brilliant-file-name.zip" 
# The temp file will be deleted some time... 
t.close 

Sadece zos.put_next_entry('myfolder/some-funny-name.jpg') için zos.put_next_entry('some-funny-name.jpg') değişti ve ortaya çıkan zipfile dosyalar var myfolder denilen iç içe geçmiş bir klasör vardı.

+1

Sizin yönteminiz güzel çalıştı, teşekkürler! Neredeyse "zipruby" ye geçtim, ama artık devam ediyor gibi görünmüyor. – rkallensee