我正在改编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
我能够让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