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

如何在Rails 5中使用Carrierwave上传大文件

嗨,我来帮你搞定这个大文件上传的问题!不管是Windows开发环境还是Linux生产环境,大文件上传的限制涉及好几层配置,咱们一层一层来梳理:

一、先解决Windows开发环境的上传报错

你在Windows下传2GB以上文件报错,大概率是这几个地方卡了:

  • 调整Rails的上传大小限制
    Rails默认限制上传文件大小在100MB左右,你需要在config/environments/development.rb里加上:

    config.action_dispatch.max_upload_size = 6.gigabytes
    

    直接设成比你要传的最大文件还大的值就行。

  • 换掉WEBrick,改用Puma
    WEBrick作为默认开发服务器,对大文件上传的支持很差,还会有默认大小限制。建议换成Puma:

    1. 确保Gemfile里有gem 'puma',执行bundle install
    2. 在config/puma.rb里配置合理的线程数(不用太激进,避免内存爆掉):
      threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
      threads threads_count, threads_count
      port        ENV.fetch("PORT") { 3000 }
      
    3. 启动服务器用rails s puma,而不是默认的rails s
  • 检查Carrierwave上传器的限制
    打开你的上传器文件(比如app/uploaders/video_uploader.rb),如果有size_range的设置,确保上限足够大:

    def size_range
      1..6.gigabytes # 允许1字节到6GB的文件
    end
    

    另外,确认你的存储目录在NTFS分区(FAT32不支持4GB以上单个文件),磁盘空间也要够。

二、生产环境(Linux)的关键配置

生产环境用Linux的话,主要要配置Nginx和应用服务器(Puma/Unicorn):

  • Nginx必须改这两个配置
    Nginx默认只允许1MB的上传,而且超时时间很短,直接改站点配置文件(比如/etc/nginx/sites-available/your_app):

    # 允许最大6GB的上传文件
    client_max_body_size 6G;
    # 延长超时时间,避免大文件上传中途中断
    proxy_connect_timeout 300s;
    proxy_send_timeout 300s;
    proxy_read_timeout 300s;
    

    改完重启Nginx:sudo systemctl restart nginx

  • Rails生产环境配置
    在config/environments/production.rb里加上同样的上传大小限制:

    config.action_dispatch.max_upload_size = 6.gigabytes
    
  • 应用服务器(Puma/Unicorn)超时设置
    如果用Puma,在config/puma.rb里延长超时时间:

    timeout 300 # 5分钟超时,足够大文件上传完成
    

    如果用Unicorn,在配置文件里加timeout 300就行。

三、上传5GB+超大型文件的终极方案:分块上传

直接传5GB以上的文件风险太高——网络中断要重传整个文件、服务器内存占用过高、超时概率大。最好的办法是用分块上传:

  • 配合云存储用carrierwave-direct
    如果你的生产环境用AWS S3(或者兼容S3的存储),用carrierwave-direct可以让前端直接把文件分块传到S3,完全绕过你的Rails服务器,既省服务器资源,又支持超大文件(S3分块上传最大支持5TB):

    1. Gemfile里加gem 'carrierwave-direct',执行bundle install
    2. 修改上传器,继承CarrierWave::Direct::Uploader:
      class VideoUploader < CarrierWave::Direct::Uploader
        # 你的上传器配置(扩展名验证、存储路径等)
      end
      
    3. 表单里用direct_upload_form helper生成上传表单,这样文件直接传到S3。
  • 自己实现分块上传(本地存储场景)
    如果用本地存储,可以自己做分块:

    1. 前端用JS把大文件切成100MB左右的小块
    2. 每次上传一块到后端,后端记录已上传的块(存在数据库里,比如记录文件ID、块序号、存储路径)
    3. 所有块上传完成后,后端把这些块合并成完整文件,再交给Carrierwave处理。
  • 用第三方前端库简化开发
    比如用Uppy或者Dropzone.js,这些库自带分块上传功能,只要后端写对应的API接口接收块就行,不用自己写前端逻辑。

四、额外要注意的点
  • 文件系统支持:Linux下用ext4或XFS,这俩都支持超大文件(ext4最大单个文件16TB),别用老的ext3
  • 内存监控:大文件上传会占用服务器内存,生产环境要监控内存使用,避免OOM(内存溢出)
  • 验证优化:Carrierwave的扩展名验证别读取整个文件内容,尽量用文件头或者扩展名判断,避免内存爆掉
  • 磁盘空间:不管本地还是云存储,都要确保有足够的空间存大文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:57:23