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

Rack-Cors导致Fine Uploader预检请求失败问题排查求助

React + Fine Uploader + Rails 5 后端文件上传解决方案

我来帮你梳理下React前端用Fine Uploader对接Rails 5后端上传文件的关键点,结合你当前的中间件配置情况来一步步排查和优化:

一、先把CORS配置做扎实

你已经把Rack::Cors放在中间件第二位,这个位置没问题,但得确保CORS规则配置正确——毕竟跨域上传的核心就是这个。打开config/initializers/cors.rb,检查配置是不是类似这样:

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    # 开发环境可以用通配符,生产环境一定要换成你的前端实际域名,比如'https://your-react-app.com'
    origins '*' 
    resource '*',
      headers: :any,
      # 要包含Fine Uploader用到的所有请求方法,OPTIONS是预检请求必须的
      methods: [:get, :post, :put, :patch, :delete, :options],
      # 暴露这两个响应头,Fine Uploader需要它们处理下载和上传进度
      expose: ['Content-Disposition', 'X-Content-Length'] 
  end
end

小提示:虽然你现在把Rack::Cors放在第二位,只要它在ActionDispatch::Static之前就没问题,但用insert_before 0把它设为第一个中间件会更稳妥,避免静态资源请求先被处理导致CORS头没加上。

二、React里的Fine Uploader配置要踩对坑

在你的React组件里初始化Fine Uploader时,有几个关键配置不能漏:

import FineUploaderTraditional from 'fine-uploader-wrappers';
import TraditionalUploader from 'react-fine-uploader-traditional';

const uploader = new FineUploaderTraditional({
  options: {
    request: {
      endpoint: '/uploads', // 这里填你的Rails后端上传接口路径
      // 必须带上Rails的CSRF令牌,不然会被Rails的防护机制拦截
      customHeaders: {
        'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
      },
      // 如果Fine Uploader默认的参数名'qqfile'和你Rails控制器里的参数名不一致,在这里映射
      params: { file: 'qqfile' }
    },
    cors: {
      expected: true, // 明确告诉Fine Uploader我们要处理跨域请求
      sendCredentials: true // 如果前端和后端域名不同,且需要传递Cookie的话开启这个
    },
    // 大文件上传建议开分片,避免超时或者服务器限制
    chunking: {
      enabled: true
    }
  }
});

// 然后在组件里渲染上传组件
function FileUploader() {
  return <TraditionalUploader uploader={uploader} />;
}

三、Rails后端接口要适配Fine Uploader的请求

在Rails里写上传控制器(比如UploadsController)时,要注意参数名和响应格式:

class UploadsController < ApplicationController
  # 如果已经通过customHeaders传递了CSRF令牌,这个可以不用加;如果没传递,再加上跳过验证
  # skip_before_action :verify_authenticity_token, only: [:create]
  before_action :set_upload, only: [:show, :destroy]

  def create
    # 这里的:file对应前面Fine Uploader配置里的params映射,要是没映射就用params[:qqfile]
    @upload = Upload.new(upload_params)
    if @upload.save
      # Fine Uploader需要接收{ success: true }格式的响应
      render json: { success: true }, status: :ok
    else
      # 失败时要返回错误信息,格式要符合Fine Uploader的要求
      render json: { success: false, error: @upload.errors.full_messages.join(', ') }, status: :unprocessable_entity
    end
  end

  private
    def set_upload
      @upload = Upload.find(params[:id])
    end

    def upload_params
      params.require(:upload).permit(:file)
    end
end

四、中间件顺序和Webpack代理的小细节

你的当前中间件顺序是:

  • use Webpacker::DevServerProxy
  • use Rack::Cors
  • use Rack::Sendfile
  • ...

这个顺序没问题,但要注意Webpacker::DevServerProxy会不会把上传请求拦截到webpack dev server。打开config/webpacker.yml,给dev server的proxy加个排除规则:

development:
  dev_server:
    proxy:
      enabled: true
      host: localhost
      port: 3000
      public: localhost:3000
      headers:
        Host: localhost:3000
      # 把上传接口排除在外,让请求直接到Rails后端
      exclude: ['/uploads']

这样就能保证上传请求不会被webpack代理走,而是正确到达Rails后端,CORS中间件也能正常处理跨域头了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:01:01