2017-10-12 9 views
1

Je reçois un fichier dans un params de demande par une entrée de fichier standardfichier Pass pour l'emploi active d'emploi/arrière-plan

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

Cependant, pour les grands ajouts, je voudrais faire dans un travail de fond . Les options de jobs d'arrière-plan populaires comme Sidekiq ou Resque dépendent de Redis pour stocker les paramètres, donc je ne peux pas simplement passer un objet fichier via redis.

Je pourrais utiliser un Tempfile, mais sur certaines plateformes telles que Heroku, le stockage local n'est pas fiable.

De quelles options ai-je besoin pour le rendre fiable sur n'importe quelle plateforme?

Répondre

0

D'abord vous devez enregistrer le fichier sur le stockage (local ou AWS S3). Passez ensuite filepath ou uuid comme paramètre pour le travail d'arrière-plan.

Je recommande fortement en évitant de passer Tempfile sur les paramètres. Cela stocke dans la mémoire un objet qui peut devenir obsolète, provoquant des problèmes de données obsolètes.

1

Je suggère de télécharger directement sur un service comme Amazon S3 puis de traiter le fichier comme bon vous semble dans un travail en arrière-plan. Lorsque l'utilisateur télécharge le fichier, vous pouvez vous assurer qu'il sera stocké en toute sécurité dans S3. Vous pouvez utiliser un compartiment privé pour interdire l'accès public. Ensuite, dans votre tâche d'arrière-plan, vous pouvez traiter le téléchargement en transmettant l'URI S3 du fichier et laisser votre travailleur en arrière-plan télécharger le fichier.

Je ne sais pas ce que fait votre arrière-plan avec le fichier, mais il va sans dire que le télécharger à nouveau n'est peut-être pas nécessaire. Il est stocké quelque part après tout.

J'ai déjà utilisé la gemme carrierwave-direct avec succès. Depuis que vous mentionnez Heroku, ils ont un guide détaillé pour télécharger des fichiers directement sur S3.

0

Pas tempfile

On dirait que vous voulez soit accélérer téléchargement d'images ou le pousser dans arrière-plan. Voici my suggestions from another post. Peut-être qu'ils vont vous aider si c'est ce que vous cherchez.

La raison pour laquelle j'ai trouvé cette question est que je voulais enregistrer un fichier CSV et que mon travail d'arrière-plan s'ajoutait à la base de données avec les informations de ce fichier.

J'ai une solution. Parce que votre question est un peu floue et que je suis trop paresseux pour poster ma propre question et répondre à ma propre question, je vais juste poster la réponse ici. lol

Comme les autres mecs ont dit, enregistrez le fichier sur un service de stockage en nuage. Pour Amazon, vous avez besoin de:

# 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 

Vous en avez également besoin.Utilisez le même code, mais un nom différent du seau dans 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 

Vous devez également une 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 

et un modèle

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 

et un emploi

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 

En votre co ntroller

def create 
    @file.create file_params 
end 

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