2017-10-12 3 views
1

ich eine Datei in einem Antrag params über einen Standard-DateieingabePass Datei in Active Job/Hintergrund-Job

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

jedoch für große Uploads empfangen, würde Ich mag diese in einem Hintergrund-Job zu tun . Beliebte Optionen für Hintergrundjobs wie Sidekiq oder Resque hängen von Redis ab, um die Parameter zu speichern, sodass ich ein Dateiobjekt nicht einfach durch Redis weiterleiten kann.

Ich könnte eine Tempfile verwenden, aber auf einigen Plattformen wie Heroku, ist lokaler Speicher nicht zuverlässig.

Welche Möglichkeiten habe ich, um es auf "jeder" Plattform zuverlässig zu machen?

Antwort

0

Zuerst sollten Sie Speichern Sie die Datei auf Speicher (entweder lokal oder AWS S3). Dann übergeben Sie Dateipfad oder UUID als Parameter zum Hintergrundjob.

Ich empfehle dringend zu vermeiden, Tempfile über Parameter übergeben. Dies speichert Objekte im Speicher, die veralten können und veraltete Datenprobleme verursachen.

1

Ich würde vorschlagen, direkt zu einem Service wie Amazon S3 hochladen und dann die Datei verarbeiten, wie Sie in einem Hintergrundjob passen.

Wenn der Benutzer die Datei hochlädt, können Sie sicher sein, dass sie sicher in S3 gespeichert wird. Sie können einen privaten Bucket zum Sperren des öffentlichen Zugriffs verwenden. In Ihrer Hintergrundaufgabe können Sie dann den Upload durchführen, indem Sie den S3-URI der Datei übergeben und den Hintergrund-Mitarbeiter die Datei herunterladen lassen.

Ich weiß nicht, was Ihr Hintergrundarbeiter mit der Datei tut, aber es ist selbstverständlich, dass ein erneutes Herunterladen möglicherweise nicht notwendig ist. Es ist irgendwo gespeichert.

Ich habe den carrierwave-direct Edelstein in der Vergangenheit mit Erfolg verwendet. Da Sie Heroku erwähnen, haben sie eine detaillierte für das Hochladen von Dateien direkt auf S3.

0

Kein tempfile

Es klingt wie Sie wollen entweder Hochladen von Bildern beschleunigen oder in den Hintergrund drängen. Hier sind my suggestions from another post. Vielleicht helfen sie dir, wenn du das suchst.

Der Grund, warum ich diese Frage gefunden habe, liegt daran, dass ich eine CSV-Datei speichern und meinen Hintergrundjob mit den Informationen in dieser Datei zur Datenbank hinzufügen wollte.

Ich habe eine Lösung.

Da Sie die Frage ein wenig unklar ist und ich bin zu faul, um meine eigene Frage zu stellen und meine eigene Frage zu beantworten, werde ich nur die Antwort hier posten. lol

Wie die anderen Jungs gesagt, speichern Sie die Datei auf einem Cloud-Speicherdienst. Für Amazon benötigen Sie:

# 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 

Sie brauchen das auch.Verwenden Sie den gleichen Code, aber verschiedene Bucketnamen in 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 

Sie müssen auch eine Migration

# 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 

und ein Modell

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 

und einen Job

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 

In Dein co Regler

def create 
    @file.create file_params 
end 

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