8
votes

Comment décompresser un dossier zippé avec rubyzip

Je sais comment récupérer le contenu d'un fichier zip normal avec RubyZip. Mais j'ai eu des difficultés à découvrir le contenu d'un dossier zippé et j'espère que l'un des gars de U peut m'aider.

Ceci est le code que j'utilise pour décompresser: p>

Zip::ZipFile::open(@file_location) do |zip|
 zip.each do |entry|
  next if entry.name =~ /__MACOSX/ or entry.name =~ /\.DS_Store/ or !entry.file?
  logger.debug "#{entry.name}"
  @data = entry.get_input_stream.read
  # How do i create a file from a stream?
 end
end


0 commentaires

3 Réponses :


0
votes

Je pense que votre problème n'est pas si vous devez écrire un fichier d'un flux ou non. Fondamentalement, si vous appelez fichier.new it Créez un nouveau io-Stream ( fichier est une sous-classe de io ). Par conséquent, tout ce que vous voulez faire avec le flux du zipfile devrait également fonctionner avec un fichier régulier.

Lorsque vous dites

Lorsque j'essaie ensuite de créer le fichier, il me dit que le fichier ne peut pas être trouvé

Je pense que ce qui se passe est que le répertoire parent du fichier que vous souhaitez créer n'existe pas (dans votre cas le dossier de test ). Ce que vous voulez faire, c'est quelque chose comme ça (non testé): xxx


1 commentaires

J'ai essayé votre code, mais cela ne crée que le dossier parent de l'entrée à la racine de mon projet. Je ne peux toujours pas accéder à l'entrée. C'est en fait un errno :: Enoent - Je pensais que je devrais mentionner cela. thx tho



0
votes

Je l'ai résolu en utilisant un flux et en créant un stringio. Voici le code

Zip::ZipFile::open(@file_location) do |zip|
 zip.each do |entry|
  next if entry.name =~ /__MACOSX/ or entry.name =~ /\.DS_Store/ or !entry.file?

  begin
   # the normal unzip-code
  rescue Errno::ENOENT
   # when the entry can not be found
   @data = entry.get_input_stream.read
   @file = StringIO.new(@data)
   @file.class.class_eval { attr_accessor :original_filename, :content_type }
   @file.original_filename = entry.name
   @file.content_type = MIME::Types.type_for(entry.name)

   # save it / whatever
  end
 end
end


1 commentaires

Cette première ligne devrait être: zip :: zipfile.open (@file_location) faire | zip |



6
votes

J'ai trouvé qu'une approche plus simple basée sur Jhwist a fonctionné OK:

Zip::File.open(@file_location) do |zipfile|
  zipfile.each do |entry|
    # The 'next if...' code can go here, though I didn't use it
    unless File.exist?(entry.name)
      FileUtils::mkdir_p(File.dirname(entry.name))
      zipfile.extract(entry, entry.name) 
    end
  end
end


2 commentaires

Cette approche ne préserve pas les autorisations des fichiers. Comment puis-je préserver les autorisations après avoir extraites?


C'est bizarre que zip.mkdir ne fonctionne pas comme mkdir_p si entrée.name inclut tout le chemin. Pour cette raison, nous devons utiliser fileautils (