将文件传递给活动作业/后台作业

我通过标准文件输入在请求参数中收到一个文件

def create file = params[:file] upload = Upload.create(file: file, filename: "img.png") end 

但是,对于大型上传,我想在后台工作中执行此操作。 像Sidekiq或Resque这样的流行后台作业选项依赖于Redis来存储参数,所以我不能只通过redis传递文件对象。

我可以使用Tempfile ,但在某些平台上,例如Heroku,本地存储不可靠。

我有什么选择让它在“任何”平台上可靠?

我建议直接上传到像Amazon S3这样的服务,然后按照你认为适合后台工作的方式处理文件。

当用户上传文件时,您可以确保它将安全地存储在S3中。 您可以使用专用存储桶来禁止公共访问。 然后,在后台任务中,您可以通过传递文件的S3 URI来处理上传,并让后台工作人员下载该文件。

我不知道你的后台工作人员对该文件做了什么,但不用说再次下载它可能没有必要。 它毕竟存放在某个地方。

我过去使用过carrierwave-direct gem并取得了成功。 由于你提到Heroku,他们有一个详细的指南 ,可以直接将文件上传到S3。

没有临时文件

听起来你想要加快图像上传速度或将其推送到后台。 以下是我在另一篇文章中的建议 。 也许他们会帮助你,如果这是你正在寻找的。

我发现这个问题的原因是因为我想保存一个CSV文件并将我的后台作业添加到该文件中的信息的数据库中。

我有一个解决方案。

因为你的问题有点不清楚,我懒得发表自己的问题并回答我自己的问题,我只想在这里发布答案。 大声笑

像其他人说的那样,将文件保存在某些云存储服务上。 对于亚马逊,您需要:

 # Gemfile gem 'aws-sdk', '~> 2.0' # for storing images on AWS S3 gem 'paperclip', '~> 5.0.0' # image processor if you want to use images 

你也需要这个。 在production.rb使用相同的代码但不同的存储桶名称

 # config/environments/development.rb Rails.application.configure do config.paperclip_defaults = { storage: :s3, s3_host_name: 's3-us-west-2.amazonaws.com', s3_credentials: { bucket: 'my-bucket-development', s3_region: 'us-west-2', access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'] } } end 

您还需要迁移

 # db/migrate/20000000000000_create_files.rb class CreateFiles < ActiveRecord::Migration[5.0] def change create_table :files do |t| t.attachment :import_file end end end 

和一个模型

 class Company < ApplicationRecord after_save :start_file_import has_attached_file :import_file, default_url: '/missing.png' validates_attachment_content_type :import_file, content_type: %r{\Atext\/.*\Z} def start_file_import return unless import_file_updated_at_changed? FileImportJob.perform_later id end end 

和一份工作

 class FileImportJob < ApplicationJob queue_as :default def perform(file_id) file = File.find file_id filepath = file.import_file.url # fetch file response = HTTParty.get filepath # we only need the contents of the response csv_text = response.body # use the csv gem to create csv table csv = CSV.parse csv_text, headers: true p "csv class: #{csv.class}" # => "csv class: CSV::Table" # loop through each table row and do something with the data csv.each_with_index do |row, index| if index == 0 p "row class: #{row.class}" # => "row class: CSV::Row" p row.to_hash # hash of all the keys and values from the csv file end end end end 

在你的控制器中

 def create @file.create file_params end def file_params params.require(:file).permit(:import_file) end 

首先,您应该文件保存在存储上(本地或AWS S3)。 然后将filepath或uuid作为参数传递给后台作业。

我强烈建议避免在参数上传递Tempfile 。 这会将对象存储在内存中,该对象可能会过时,从而导致过时的数据问题。

Interesting Posts