【问题标题】:rails send_data can't handle large file (2G+)rails send_data 无法处理大文件(2G+)
【发布时间】:2023-03-08 10:54:01
【问题描述】:

我的环境:

  • Mac:10.12.4
  • 内存:16G
  • 红宝石:2.1.4
  • 导轨: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

我尝试使用 ruby​​zip 来代替输出流:

    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

任何想法将不胜感激。

谢谢。

【问题讨论】:

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


    【解决方案1】:

    您可能想改用send_file。根据documentation

    发送文件,默认情况下一次传输 4096 个字节。这边走 整个文件不需要一次读入内存。这使得 甚至可以发送大文件。您可以选择关闭 流式传输并一次发送整个文件。

    【讨论】:

    • 感谢您的回复。我尝试使用 send_file,但仍然无法正常工作。大文件问题(大于 2206004964 字节)仍然存在。我尝试了不同的网络服务器:Thin 和 Puma (3.8.2),还是一样。
    • 您能否编辑您的问题并使用 send_file 发布新代码?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-01
    • 1970-01-01
    • 2017-01-01
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多