S3上的“ path_for” ActiveStorage附件

时间:2018-12-12 18:45:28

标签: ruby-on-rails amazon-s3 rails-activestorage

我在Heroku上托管了一个应用程序,其中一个用户可以回答测验并提交一些照片(通过Active Storage,并将文件发送到S3存储桶),而另一个用户可以看到检索的答案和照片。

我使用一种方法来让用户将测验的所有照片下载到.zip文件中,但是我一直在实时应用程序上收到此错误消息:

  

NoMethodError(#ActiveStorage :: Service :: S3Service:0x0000000006b47368>的未定义方法“ path_for”):

用于创建.zip文件的方法是:

def quiz_photos_download
  @quiz = Quiz.find(params[:quiz_id])
  @project = Project.find(@quiz.project_id)
  @photos = @quiz.room_photos

  arquivo = "#{Rails.root}/tmp/quiz_photos.zip"

  Zip::File.open(arquivo, Zip::File::CREATE) do |zipfile|
    @photos.each do |photo|
      zipfile.add(photo.filename, ActiveStorage::Blob.service.send(:path_for, photo.key))
    end
  end
      send_file(arquivo, :type => 'application/zip', :filename => "Fotos "+@project.name+".zip")
end

我可以在项目视图上显示用户发送的所有图像,并且在本地运行代码时批量下载工作正常。

对此有何想法?

1 个答案:

答案 0 :(得分:3)

您正在使用S3后端存储Active Storage附件,因此文件不在某个S3存储桶中,而不是在文件系统中的任何位置。没有磁盘服务可以使用的路径。

您必须从S3下载图像并将数据直接添加到zip文件中,而不是通过文件的路径将文件添加到zip文件中。像这样:

# The streaming API is a bit easier for this.
Zip::OutputStream.open(arquivo) do |zip|
  @photos.each do |photo|
    zip.put_next_entry(photo.filename)
    zip.print(photo.download)
  end
end

photo.download调用会将文件从S3下载到内存中的字符串中。这样可能会消耗更多的内存,因此您可能想使用ActiveStorage::Downloading模块来帮助将附件下载到临时文件,有关使用ActiveStorage::Downloading的一些信息,请参见Active Storage Overview Guide

此过程可能会变慢并且占用大量资源,因此您可能需要将zip创建推迟到后台作业,然后在作业完成时通知此人。