RubyZip docx使用write_buffer代替open的问题。

问题描述 投票:0回答:1

我正在改编RubyZip递归压缩的例子(在此找到)来代替open,并遇到了一系列的问题。我之所以这样做是因为我制作的zip压缩包里有word文档,而我在打开这些word文档时出现了错误。因此,我正在尝试RubyZip建议的变通方法,即使用write_buffer代替open (例子).

问题是,我得到的错误是因为我使用的是绝对路径,但我不知道如何解决这个问题。我得到的错误是 "#/',name must not start with >"

其次,我不知道该怎么做才能缓解word文档的问题。当我使用我的原始代码时,它工作并创建了一个实际的压缩文件,该压缩文件中的任何word文档在打开时都会出现以下错误。"Word发现无法读取的内容,你想恢复这个文档的内容吗?如果你信任这个文档的来源,请点击 "是"。不可读内容错误是我走上尝试使用write_buffer之路的原因。

希望得到任何帮助。

这是我目前使用的代码。

require 'zip'
require 'zip/zipfilesystem'

module AdvisoryBoard
  class ZipService
    def initialize(input_dir, output_file)
      @input_dir = input_dir
      @output_file = output_file
    end

    # Zip the input directory.
    def write
      entries = Dir.entries(@input_dir) - %w[. ..]
      path = ""

      buffer = Zip::ZipOutputStream.write_buffer do |zipfile|
        entries.each do |e|
          zipfile_path = path == '' ? e : File.join(path, e)
          disk_file_path = File.join(@input_dir, zipfile_path)

          @file = nil
          @data = nil

          if !File.directory?(disk_file_path)
            @file = File.open(disk_file_path, "r+b")
            @data = @file.read

            unless [@output_file, @input_dir].include?(e)
              zipfile.put_next_entry(e)
              zipfile.write @data
            end

            @file.close
          end
        end

        zipfile.put_next_entry(@output_file)

        zipfile.put_next_entry(@input_dir)
      end

      File.open(@output_file, "wb") { |f| f.write(buffer.string) }
    end
  end
end
ruby zip docx rubyzip
1个回答
0
投票

我能够让word文档打开,而没有任何警告或损坏。下面是我最后做的事情。

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

  class ZipService
    # Initialize with the directory to zip and the location of the output archive.
    def initialize(input_dir, output_file)
      @input_dir = input_dir
      @output_file = output_file
    end

    # Zip the input directory.
    def write
      entries = Dir.entries(@input_dir) - %w[. ..]

      ::Zip::File.open(@output_file, ::Zip::File::CREATE) do |zipfile|
        write_entries entries, '', zipfile
      end
    end

    private

    # A helper method to make the recursion work.
    def write_entries(entries, path, zipfile)
      entries.each do |e|
        zipfile_path = path == '' ? e : File.join(path, e)
        disk_file_path = File.join(@input_dir, zipfile_path)

        if File.directory? disk_file_path
          recursively_deflate_directory(disk_file_path, zipfile, zipfile_path)
        else
          put_into_archive(disk_file_path, zipfile, zipfile_path, e)
        end
      end
    end

    def recursively_deflate_directory(disk_file_path, zipfile, zipfile_path)
      zipfile.mkdir zipfile_path
      subdir = Dir.entries(disk_file_path) - %w[. ..]
      write_entries subdir, zipfile_path, zipfile
    end

    def put_into_archive(disk_file_path, zipfile, zipfile_path, entry)
      if File.extname(zipfile_path) == ".docx"
        Zip::File.open(disk_file_path) do |zip|
          doc = zip.read("word/document.xml")
          xml = Nokogiri::XML.parse(doc)
          zip.get_output_stream("word/document.xml") {|f| f.write(xml.to_s)}
        end
        zipfile.add(zipfile_path, disk_file_path)
      else
        zipfile.add(zipfile_path, disk_file_path)
      end
    end
  end

© www.soinside.com 2019 - 2024. All rights reserved.