如何仅在内存中修改zip文件?

我有一个Ruby应用程序,我需要修改现有的zip文件。

我想在内存中构建zip文件并流回字节而无需将文件写入文件系统。 如果我最终在Heroku上托管这个,我不认为我可以写入文件系统。 有谁知道这样做的方法?

我查看了Zip :: ZipFile,但看起来它总是想写入文件系统。 我认为“基于java实现”我将能够获得压缩文件的字节,你可以在java中做,但我没有办法做到这一点。


编辑:

我要问的基本上与此相同,但是对于Ruby而不是Python: 函数创建内存中的zip文件并作为http响应返回

有同样的问题,通过关闭文件并读取数据并将其作为send_data流式传输来使其工作

然后找到另一个在heroku上工作正常的库,可以处理内存缓冲区:它是zipruby (不是rubyzip)。

buffer = '' Zip::Archive.open_buffer(buffer, Zip::CREATE) do |archive| files.each do |wood, report| title = wood.abbreviation+".txt" archive.add_buffer(title, report); end end file_name = "dimter_#{@offer.customerName}_#{Time.now.strftime("%m%d%Y_%H%M")}.zip" send_data buffer, :type => 'application/zip', :disposition => 'attachment', :filename => file_name 

这是一篇博文 ,介绍了这个问题。 它使用Tempfile ,对我来说似乎是一个很好的解决方案(虽然阅读了一些有用的额外讨论的评论)。

一个例子,来自post:

 def download_zip(image_list) if !image_list.blank? file_name = "pictures.zip" t = Tempfile.new("my-temp-filename-#{Time.now}") Zip::ZipOutputStream.open(t.path) do |z| image_list.each do |img| title = img.title title += ".jpg" unless title.end_with?(".jpg") z.put_next_entry(title) z.print IO.read(img.path) end end send_file t.path, :type => 'application/zip', :disposition => 'attachment', :filename => file_name t.close end end 

这个解决方案应该与Heroku很好用 。

您可以随时修补Zip :: ZipFile的new方法和open方法,以允许使用StringIO句柄,然后将I / O直接用于内存。

在这里提出我自己的问题的答案,我认为更适合我想要做的事情。 这个方法确实没有文件(没有临时文件)。

由于ZipFile扩展,并且实际上只是ZipCentralDirectory的一堆便利方法,您可以直接使用ZipCentralDirectory而不是ZipFile。 这将使您使用IO流来创建和编写zip文件。 再加上使用StringIO,您可以从字符串中执行此操作:

  # load a zip file from a URL into a string resp = Net::HTTP.new("www.somewhere.com", 80).get("/some.zip") zip_as_string = response.body # open as a zip zip = Zip::ZipCentralDirectory.read_from_stream(StringIO.new(zip_as_string)) # work with the zip file. # i just output the names of each entry to show that it was read correctly zip.each { |zf| puts zf.name } # write zip back to an output stream out = StringIO.new zip.write_to_stream(out) # use 'out' or 'out.string' to do whatever with the resulting zip file. out.string 

更新:

这实际上根本不起作用。 它会写一个可读的zip文件,但只有zip文件的’目录’。 所有内部文件都是0长度。 进一步深入Zip实现,看起来它只在内存中保存zip条目“元数据”,并返回到底层文件以读取其他所有内容。 基于此,看起来根本不可能在不写入文件系统的情况下使用Zip实现。