You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 7.1.3如何通过button_to或link_to实现文件下载?

Rails 7.1.3 文件下载功能问题及解决办法

问题场景

在Rails 7.1.3环境下,尝试通过button_to或link_to为用户提供文件下载功能,相关代码如下:

视图代码

<%= button_to "Download Cat Photo", controller: "my_cont", action: "export", method: :post %>

控制器代码

def export
    begin
      tmpzip = Tempfile.new("tmp.zip")

      Zip::OutputStream.open(tmpzip) {|zos|}

      Zip::File.open(tmpzip.path, Zip::File::CREATE) do |zip|
        zip.add("kitty.jpg", "app/assets/images/curiouscat.jpg")
      end

      zip_data = File.read(tmpzip.path)

      send_data(zip_data,
        type: 'application/zip',
        disposition: 'attachment',
        filename: 'kitty.zip')
    ensure
      tmpzip.close
      tmpzip.unlink
    end
end

问题现象

点击按钮后,Firefox和Chrome抛出错误:Form responses must redirect to another location.;若在export方法末尾添加redirect_to,则触发“重复调用Redirect或Render”的错误。Rails控制台显示Sent data kitty.zip,说明zip文件已成功生成,但浏览器未弹出下载提示。

已尝试的操作:

  • 将按钮请求方法改为GET
  • 添加data: {turbo: :false}参数
  • 改用link_to,但跳转至Controller#show且仍无下载提示

疑问

  1. 操作中存在哪些错误?
  2. button_to和link_to哪个更适合文件下载场景?

解决方法

  1. 视图层调整:使用link_to实现下载功能:
<%= link_to "Download", {controller: "my_cont", action: "export"} %>
  1. 路由配置:核心问题是未给export动作配置GET路由,需在routes.rb中添加:
get "/dashboard/export", to: "dashboard#export"

执行rails routes命令可验证路由是否生效,生效后会显示:

dashboard_export GET        /dashboard/export(.:format)         dashboard#export

场景适配说明

文件下载属于幂等性操作(多次请求不会改变服务器状态),符合HTTP GET方法的语义,因此更适合用link_to(默认发送GET请求)。而button_to默认生成POST表单,POST请求通常用于修改服务器状态的操作,且Rails Turbo对POST表单的响应要求必须返回重定向,这正是最初报错的核心原因。


内容的提问来源于stack exchange,提问作者newser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 02:22:27