简体   繁体   English

ActiveStorage 从 S3 服务上的附件对象下载文件/IO?

[英]ActiveStorage download File / IO from attachment object on S3 service?

After the file is uploaded, I want to analyze and immediately process.文件上传后,我想分析并立即处理。

I'm currently attaching then processing each:我目前正在附加然后处理每个:

current_account.archives.attach(archive_params)
current_account.archives.each do |archive|
  Job.enqueue(AccountArchiveImportJob.new(current_account.id, archive.id))
end

In the job i'm opening the CSV and parsing junk在工作中,我打开 CSV 并解析垃圾

attachment = Account.find(account_id).archives.where(id: archive_id).first

CSV.parse(attachment.download) do |row|
  do_stuff_with_the_row(row)
end

I would like to do something like:我想做类似的事情:

CSV.foreach(attachment.open) do |row|
  do_stuff_with_the_row(row)
end

I cannot find documentation that allows converting the attachment back into a FILE我找不到允许将附件转换回文件的文档

At least from Rails 6.0 rc1:至少从 Rails 6.0 rc1 开始:

model.attachment_changes['attachment_name'].attachable

will give you IO of the original TmpFile BEFORE it is uploaded.上传之前为您提供原始 TmpFile 的 IO。

Rails-6 we will get a download method that will yield a file but you can get this very easily! Rails-6 我们将获得一个download方法,该方法将生成一个文件,但您可以很容易地获得它!

Add this downloader.rb file as an initializer 添加此downloader.rb文件作为初始化程序

Then given this model然后给出这个模型

class Business < ApplicationRecord
  has_one_attached :csvfile
end

you can do你可以做

ActiveStorage::Downloader.new(csvfile).download_blob_to_tempfile do |file|
  CSV.foreach(file.path, {headers: true}) do |row|
    do_something_with_each_row(row.to_h)
  end
end

EDIT : not sure why this took me to so long to find service_url .编辑:不知道为什么我花了这么长时间才找到service_url Way more simple, but has been noted that service_url should not be shown to users方式更简单,但已注意到不应向用户显示service_url

open(csvfile.service_url)

You can get the file path from the attachment, and then open the file.您可以从附件中获取文件路径,然后打开该文件。

path = ActiveStorage::Blob.service.send(:path_for, attachment.key)
File.open(path) do |file|
    #...
end

From Rails 5.2 official guide来自 Rails 5.2 官方指南

class VirusScanner
  include ActiveStorage::Downloading

  attr_reader :blob

  def initialize(blob)
    @blob = blob
  end

  def scan
    download_blob_to_tempfile do |file|
      system 'scan_virus', file.path
    end
  end
end

So you can do所以你可以做

  include ActiveStorage::Downloading

  attr_reader :blob

  def initialize(blob)
    @blob = blob
  end

  def perform
    download_blob_to_tempfile do |file|
      CSV.foreach(file.path, {headers: true}) do |row|
        do_something_with_each_row(row.to_h)
      end
    end
  end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM