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

Rails 5应用移动端POST请求被识别为下载问题求助

解决iOS Safari中Rails button_to Ajax请求触发下载的问题

首先咱们来定位核心问题:你遇到的iOS端下载提示,本质是浏览器没有把这个请求识别成Ajax请求,而是当成了普通的表单提交;再加上返回204无内容状态码,iOS Safari会把空响应当成待下载的文件,这才弹出了下载失败的提示。

下面是具体的修复步骤:

1. 修正button_to的remote: true参数位置

你的button_to代码里把remote: true放在了路由参数哈希里,这会让它变成URL的query参数(就是你看到的?remote=true),而不是让Rails生成UJS需要的data-remote="true"属性。正确写法应该把remote: true移到第二个选项哈希中:

<%= button_to('VOTE FOR FIRST', 
              { controller: 'full_calls', action: 'vote_for_first', id: @full_call }, 
              { class: "btn btn-outline-secondary btn-sm vote-btn", remote: true }) %>

这样Rails会自动给按钮加上data-remote="true",Turbolinks/UJS就会把这个请求处理成Ajax,而不是普通表单提交。

2. 完善控制器的vote_for_first方法

你的控制器方法有两个问题:一是没通过params[:id]找到对应的@full_call,二是没有处理Ajax请求的响应格式,默认返回HTML+204状态码,这会触发iOS的下载行为。修改后的代码如下:

def vote_for_first
  # 先找到对应的记录
  @full_call = FullCall.find(params[:id])
  @full_call.first_vote += 1
  
  if @full_call.save
    # 针对Ajax请求返回JSON/JS,用200状态码避免iOS处理204的问题
    respond_to do |format|
      format.js { render json: { success: true }, status: :ok }
      # 兼容非Ajax请求的降级处理
      format.html { redirect_to @full_call, notice: "Vote recorded!" }
    end
  else
    respond_to do |format|
      format.js { render json: { error: "Vote failed" }, status: :unprocessable_entity }
      format.html { redirect_to @full_call, alert: "Failed to record vote" }
    end
  end
end

3. 调整JS事件绑定逻辑

你原来的JS绑定click事件,但UJS处理Ajax有自己的事件体系,用ajax:success和ajax:error事件会更可靠(确保请求成功后再执行操作,而不是点击就触发):

$(document).on('turbolinks:load', function() {
  $('.vote-btn')
    .on('ajax:success', function() {
      $(this).attr('disabled', true);
      $('#full-call-alert').append("<h5>Thanks for voting!</h5>").hide().slideDown('slow');
    })
    .on('ajax:error', function() {
      $('#full-call-alert').append("<h5>Sorry, your vote didn't go through. Please try again.</h5>").hide().slideDown('slow');
    });
});

4. 验证路由参数

你的路由post 'vote_for_first', to: 'full_calls#vote_for_first'是没问题的,修正button_to后,id参数会正确传递到params[:id],控制器能找到对应的记录。

做完这些调整后,iOS Safari应该会正确识别这是Ajax请求,返回200状态码的JSON响应,不会再触发下载提示,用户也能停留在/show页面完成投票。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:02:57