Errno :: EINVAL无效的参数@ io_fread

Kyl*_*cot 5 ruby

我正在尝试下载〜2GB的文件并将其写入本地文件,但是遇到了这个问题:

在此处输入图片说明

这是适用的代码:

  File.open(local_file, "wb") do |tempfile|
    puts "Downloading the backup..."

    pbar = nil
    open(backup_url,
         :read_timeout => nil,
         :content_length_proc => lambda do |content_length|
           if content_length&.positive?
             pbar = ProgressBar.create(:total => content_length)
           end
         end,
         :progress_proc => ->(size) { pbar&.progress = size }) do |retrieved|
          begin
            tempfile.binmode
            tempfile << retrieved.read
            tempfile.close
          rescue Exception => e
            binding.pry
          end
    end
Run Code Online (Sandbox Code Playgroud)

Jos*_*ter 3

分块读取文件。

导致问题的行在这里:

tempfile << retrieved.read

这会将整个内容读取到内存中,然后再将其写入tempfile. 如果内容很小,这没什么大不了的,但如果内容很大(多大取决于系统、配置、操作系统和可用资源),这可能会导致错误Errno::EINVAL,例如Invalid argument @ io_freadInvalid argument @ io_write

要解决此问题,请分块读取内容并将每个块写入tempfile. 像这样的东西:

tempfile.write( retrieved.read( 1024 ) ) until retrieved.eof?
Run Code Online (Sandbox Code Playgroud)

这将获取字节块1024并将每个块写入tempfile直到retrieved到达文件末尾(即.eof?)。

如果retrieved.read不带尺寸参数,您可能需要转换retrieved为 a StringIO,如下所示:

retrievedIO = StringIO.new( retrieved )
tempfile.write( retrievedIO.read( 1024 ) ) until retrievedIO.eof?
Run Code Online (Sandbox Code Playgroud)