rails send_data无法处理大文件(2G +)

时间:2017-04-04 01:37:22

标签: ruby-on-rails ruby large-files

我的环境:

  • Mac:10.12.4
  • 内存:16G
  • ruby​​:2.1.4
  • rails:3.2.22.5
  • 网络服务器:瘦1.7.0

当文件大小低于2G时,一切顺利。

class ItemListsController < ApplicationController
...
    send_data IO.read(zip_path), :type => 'application/zip',
        :disposition => 'attachment',
        :filename => file_name

但是,当文件大小大于2G时,会引发异常:

Errno::EINVAL: Invalid argument @ io_fread

我尝试使用rubyzip来输出流:

    compressed_filestream = Zip::OutputStream.write_buffer do |zos|
      files.each do |file|
        zos.put_next_entry file[1]
        zos.write File.open(file[0], 'r').read
      end
    end

    compressed_filestream.rewind

    send_data compressed_filestream.read, :type => 'application/zip',
              :disposition => 'attachment',
              :filename => file_name

进一步详细说明的例外情况:

Unexpected error while processing request: integer 2206004964 too big to convert to `int'
/Users/karl/.rvm/gems/ruby-2.1.4@hcsvlab/gems/eventmachine-1.0.3/lib/em/connection.rb:328:in `send_data'

似乎send_data会将整个文件读入内存然后再发回数据。

我原来的计划是找到一些提供“缓冲区”的方法,这样send_data会从缓冲区中读取而不是读取整个文件,但是在API中找不到这样的选项

https://apidock.com/rails/ActionController/DataStreaming/send_data

任何想法都将不胜感激。

感谢。

1 个答案:

答案 0 :(得分:0)

您可能希望改用send_file。根据{{​​3}}:

  

发送文件,默认情况下一次流式传输4096个字节。这条路   整个文件不需要立即读入内存。这使得   发送大型文件是可行的。您可以选择关闭   流式传输并立即发送整个文件。