【问题标题】:RubyZip docx issues with write_buffer instead of openRubyZip docx 问题与 write_buffer 而不是 open
【发布时间】:2020-05-27 20:26:45
【问题描述】:

我正在调整 RubyZip 递归压缩示例 (found here) 以使用 write_buffer 而不是 open,并且遇到了许多问题。我这样做是因为我正在制作的 zip 存档中包含 word 文档,并且在打开这些 word 文档时出现错误。因此,我正在尝试 RubyZip 建议的解决方法,即使用 write_buffer 而不是 open (example found here)。

问题是,我遇到了错误,因为我使用的是绝对路径,但我不确定如何解决这个问题。我收到错误“#//',名称不能以 /> 开头”

其次,我不确定如何缓解 Word 文档的问题。当我使用我的原始代码(该代码有效并创建了一个实际的 zip 文件)时,该 zip 文件中的任何 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

【问题讨论】:

  • 您提到了两种不同的错误场景,但不清楚这些错误是什么。您能否扩展您的问题以包括您看到的特定错误?
  • 没问题! @StephenCrosby:我扩展了这个问题,包括我遇到的错误

标签: ruby zip docx rubyzip


【解决方案1】:

我能够在没有任何警告或损坏的情况下打开 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

【讨论】:

    猜你喜欢
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 2015-10-07
    • 2017-04-08
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    • 2011-08-11
    相关资源
    最近更新 更多