我有一个Ruby应用程序,我需要修改现有的zip文件。
我想在内存中构建zip文件并将字节流回传而无需将文件写入文件系统。如果我最终在Heroku上托管这个,我不认为我可以写入文件系统。有谁知道这样做的方法?
我看了Zip::ZipFile,但看起来总是想要写入文件系统。我认为“基于java实现”我可以获得压缩文件的字节,你可以在java中做,但我没有办法做到这一点。
编辑:
我所要求的基本上与此相同,但对于Ruby而不是Python: Function to create in-memory zip file and return as http response
答案 0 :(得分:4)
有同样的问题,通过关闭文件并读取数据并将其作为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
答案 1 :(得分:3)
这是一个处理此问题的blog post。它使用Tempfile,对我来说似乎是一个很好的解决方案(尽管通过评论阅读了一些有用的额外讨论)。
一个例子,来自帖子:
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
答案 2 :(得分:1)
您可以随时修补Zip :: ZipFile的new
和open
方法以允许使用StringIO句柄,然后将I / O直接写入内存。
答案 3 :(得分:1)
在这里提出我自己的问题的答案,我认为更适合我想要做的事情。这个方法实际上没有文件(没有临时文件)。
由于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实现。