Invalid/damaged 使用 send_data 下载 PowerPoint

Invalid/damaged download using send_data with PowerPoint

我正在使用 powerpoint gem 生成 PowerPoint,直到现在我一直在使用 send_file,但现在我想使用 send_data。这样做的原因是 send_data 阻止应用程序在调用完成之前执行任何其他操作,而 send_file 允许应用程序在文件下载时继续执行,有时,由于巧合的时间,这会导致文件被删除 之前 用户告诉他们的浏览器开始下载,网络服务器完成发送文件,因此下载了一个空白或不完整的文件。

这是我创建 PowerPoint 的方式:

#Creating the PowerPoint
@deck = Powerpoint::Presentation.new
        
# Creating an introduction slide:    
title = 'PowerPoint'
subtitle = "created by #{username}"
@deck.add_intro title, subtitle
        
blah blah logic to generate slides

# Saving the pptx file.
pptname = "#{username}_powerpoint.pptx"
@deck.save(Rails.root.join('tmp',pptname)) 

现在,谈谈我的尝试。我的第一直觉是调用如下:

File.open(Rails.root.join('tmp',"#{pptname}"), 'r') do |f|


send_data f.read, :filename => filename, :type => "application/vnd.ms-powerpoint", :disposition => "attachment"
end

我也试过直接发送 @deck:

    send_data @deck, :filename => pptname, :disposition => "attachment", :type => "application/vnd.ms-powerpoint"

阅读结束时文件比预期的要大,甚至无法打开,发送 @deck 结果生成的 PowerPoint 幻灯片只有一张标题:#Powerpoint::Presentation :0x64f0dd0(又名 powerpoint object)。

不确定如何将 object 或文件转换为 send_data 正在寻找的二进制格式。

您需要以二进制方式打开文件:

path = @deck.save(Rails.root.join('tmp',pptname))
File.open(path, 'r', binmode: true) do |f|
  send_data f.read, filename: filename, 
                    type: "application/vnd.ms-powerpoint", 
                    disposition: "attachment"
end

这也可以通过在文件 class.

的实例上调用 #binmode 方法来完成
send_data @deck, ...

将不起作用,因为它在对象上调用 to_s。由于 Powerpoint::Presentation 没有实现 #to_s 方法,您将获得默认的 Object#to_s.