8

rubyzip を使用して通常の zip ファイルの内容を取得する方法を知っています。しかし、圧縮されたフォルダーの内容を解凍するのに問題がありました。どなたか助けていただければ幸いです。

これは私が解凍するために使用するコードです:

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 = File.new("#{Rails.root.to_s}/tmp/#{entry.name}")
 end
end

entry.name は、zip ファイル内のファイルの名前を教えてくれます。これは、通常の zip ファイルで完全に機能します。ただし、フォルダーから zip ファイルを作成すると、エントリの名前は test-folder/test.pdf のようになります。その後、ファイルを作成しようとすると、ファイルが見つからないことがわかります。これはおそらく、zip 内にある "test" フォルダー内にあるためです。

エントリがフォルダであることを確認すると、フォルダが見つかりません。したがって、解決策は、エントリをストリームとして読み取り、ファイルとして保存することだと思いました。エントリ ストリームを取得するのは簡単ですが、ファイルとして保存するにはどうすればよいですか? これは私がこれまでに得たものです。

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

基本的に私の質問は、ストリームからファイルを作成するにはどうすればよいですか? それとも、私よりも簡単なアプローチがありますか?

===編集=== 私はクリップを使ってファイルを保存しています。

4

3 に答える 3

6

jhwist に基づくより単純なアプローチがうまく機能することがわかりました。

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

条件は明らかにオプションですが、それがないと、コードが既存のファイルを上書きしようとするとエラーが発生します。

于 2015-04-15T14:50:46.593 に答える
0

あなたの問題は、ストリームからファイルを書き込む必要があるかどうかではないと思います。基本的に、これを呼び出すFile.new、新しい IO-Stream (FileのサブクラスIO) が作成されます。したがって、zipfile からのストリームでやりたいことは、通常のファイルでも機能するはずです。

あなたが言う時

その後、ファイルを作成しようとすると、ファイルが見つからないと表示されます

何が起こるかは、作成したいファイルの親ディレクトリが存在しないことだと思います(あなたの場合はtest-folder.)。あなたがしたいことはそのようなものです(テストされていません):

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}"
   FileUtils::mkdir_p(File.dirname(entry.name)) # might want to check if it already exists    
   @data = File.new("#{Rails.root.to_s}/tmp/#{entry.name}")
 end
end
于 2011-05-16T14:51:03.087 に答える
0

ストリームを使用して StringIO を作成することで解決しました。ここにコードがあります

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
于 2011-05-17T10:23:08.520 に答える