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

如何在Rails 6中通过rubyzip实现含ActiveStorage文件的Zip打包下载功能

Rails 6 实现多层级目录Zip下载功能实操步骤

1. 安装依赖

首先在Gemfile中添加rubyzip依赖:

gem 'rubyzip', require: 'zip'

执行bundle install安装完成后重启服务。

2. 配置路由

在config/routes.rb中给listings添加成员路由:

resources :listings do
  member do
    get :download_zip
  end
end

3. 编写控制器逻辑

在app/controllers/listings_controller.rb中添加download_zip方法,核心逻辑包含预加载关联数据避免N+1、流式生成Zip包直接返回给浏览器:

def download_zip
  # 预加载关联数据,避免N+1查询
  @listing = Listing.includes(offers: :attachments).find(params[:id])
  # 配置响应头,告知浏览器返回Zip下载文件
  response.headers['Content-Type'] = 'application/zip'
  response.headers['Content-Disposition'] = "attachment; filename=\"#{@listing.name.parameterize}.zip\""
  response.headers['Last-Modified'] = Time.now.httpdate.to_s

  # 流式生成Zip,不占用服务器本地磁盘存储
  Zip::OutputStream.write_buffer do |zip|
    @listing.offers.each do |offer|
      # 生成Offer层级目录,parameterize处理特殊字符避免路径错误
      offer_dir = "#{@listing.name.parameterize}/#{offer.id}_#{offer.title.parameterize}/"
      # 往Zip中写入目录
      zip.put_next_entry(offer_dir)

      offer.attachments.each do |attachment|
        # 生成文件在Zip中的完整路径,加attachment.id避免同目录下重名文件覆盖
        file_path = "#{offer_dir}#{attachment.id}_#{attachment.name.parameterize}"
        zip.put_next_entry(file_path)
        # 读取ActiveStorage文件内容写入Zip
        attachment.attachment_file.open do |file|
          zip.write file.read
        end
      end
    end
  end.tap do |zip_buffer|
    zip_buffer.rewind
    # 直接输出Zip流到浏览器
    response.body = zip_buffer.read
  end
end

4. 页面添加下载按钮

在app/views/listings/show.html.erb对应位置添加下载按钮,注意关闭Turbo/UJS的默认异步请求处理:

<%= link_to '下载Zip', download_zip_listing_path(@listing), class: 'btn btn-primary', data: { turbo: false, disable_with: '正在生成压缩包...' } %>

注意事项

  • 若你的应用存在大文件、多附件的场景,建议将Zip生成逻辑放到Sidekiq等后台任务中执行,生成完成后给用户发下载通知,避免请求超时
  • 需自行添加权限校验逻辑,确保只有有权限访问该Listing的用户才能触发下载操作
  • 路径生成时统一使用parameterize处理特殊字符,避免路径遍历漏洞和Zip打包异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:27:04