我曾经有过类似的症状。我知道这是一个旧问题,已经解决了,但我想贡献一下我的发现,因为我的情况是由不同的原因引起的。
我正在构建一个CSV文件,并使用send_file将文件发送到浏览器。在开发中它运行得很好,在生产中浏览器报告页面未找到。
以下是控制器中的操作。
def export
@campaign = LiveEmailCampaign.find params[:id]
@campaign.recipients_csv do |csv_file|
send_file csv_file,
filename: @campaign.name,
type: Mime::CSV
end
end
而CSV是从模型中的此代码构建的。
def recipients_csv
tempfile = Tempfile.new(self.name.downcase.dasherize)
CSV.open tempfile, 'w' do |csv|
recipients.each do |recipient|
csv << [recipient]
end
end
yield tempfile
end
经过几分钟的研究,我确定问题在于生产服务器上Apache中XSendFile指令与用于写入CSV数据的临时路径之间的冲突。 在我的情况下,XSendFile仅设置为应用程序根目录,而临时文件位于服务器上的 /tmp。
为了避免在服务器级别调整 XSendFile 配置,我只需指示 Tempfile 使用 Rails 应用程序中的 tmp 文件夹。
因此,我将模型方法中对 Tempfile 的调用更改为:
tempfile = Tempfile.new(self.name.downcase.dasherize)
现在,Rails和Apache再次成为朋友。我只需要重构这段代码,因为它没有显式地取消链接创建的临时文件。最佳实践是显式取消链接临时文件。