使用Tempfile在Rails中创建zip文件

7

我想在Rails中创建一个临时的.zip文件。为了创建zip文件,我正在使用rubyzip gem。

目前我正在这样做:

zfname = Tempfile.new(['somename','.zip'], Rails.root.to_s + '/tmp/')
Zip::ZipFile.open(zfname.path, Zip::ZipFile::CREATE) do |zipfile|
  zipfile.add(file, basepath + file)
end

这会生成以下错误:
Zip::ZipError: Zip end of central directory signature not found

是否可以使用Tempfile压缩文件?如果可以,下面的代码有什么问题?

2个回答

12

在我的Rails应用程序中,当我需要向用户发送zip文件时,我只需将它们存储在缓冲区中,并在控制器中使用“send data”方法。

起初我尝试使用'Tempfile',但是发送完文件后还需要删除zip文件,这很麻烦。

这是你需要的内容吗?

    Zip::OutputStream.write_buffer do |stream|
      file_paths.each_with_index do |file_path, index|
        # rename the pdf
        stream.put_next_entry("#{name}-#{index + 1}.pdf")
        # add pdf to zip
        stream.write IO.read(file_path)
      end  
    end

@AdityaShedge,在Heroku上这是否实际可行,因为dynos的内存非常有限? - Mohamad
@Mohamad 这取决于你的压缩文件有多大。在我的情况下,我知道它不会超过几MB...这对我来说是可以接受的,因为将文件写入磁盘并稍后清理它要麻烦得多。如果您的文件大小超过内存大小的1/4,则可能会出现问题。 - Aditya Shedge
@AdityaShedge 谢谢。具体来说,这会在 RAM 中构建文件,然后将其发送给用户。它不会实时流式传输文件,对吧?因为它必须先完成构建文件,然后才能将其作为响应发送。 - Mohamad
@Mohamad 是的,先构建完整文件。 - Aditya Shedge
如果存储缓冲区的变量名为“buffer”,在调用“send_data”时不要忘记调用“buffer.string”。 - Rael Gugelmin Cunha
显示剩余2条评论

8

看起来您并不需要或者想要一个Tempfile。您真正想要的是Rails.root/tmp目录下的一个随机路径。可以尝试使用以下代码:

zfpath = Rails.root.join('tmp', "somename-#{SecureRandom.hex(8)}.zip"
Zip::ZipFile.open(zfpath, Zip::ZipFile::CREATE) do |zipfile|
  zipfile.add(file, basepath + file)
end

更新:

虽然更加复杂,但是你可以在这里找到如何使用Tempfile完成这个过程的讨论 - http://thinkingeek.com/2013/11/15/create-temporary-zip-file-send-response-rails/


我能够完成你所建议的。但这不是我的目的。我想使用一个临时文件,因为这是我代码中的临时操作。我将在一步之后删除该文件。虽然你的建议也可以做到,但我特别寻找用于此目的的临时文件。谢谢。 - shivam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接