2011-12-12 9 views
5

Tôi cần phản hồi về thiết kế để tải lên và trì hoãn việc xử lý tệp bằng heroku, kẹp giấy, công việc bị trì hoãn và, nếu cần, s3. Một phần của nó đã được thảo luận ở những nơi khác nhưng tôi không thể tìm thấy một cuộc thảo luận hoàn chỉnh ở bất cứ đâu.Kẹp giấy, Công việc bị trì hoãn, S3, Heroku - thiết kế để xử lý chậm các tệp được tải lên nhạy cảm: db hoặc s3?

Mô tả Nhiệm vụ:

  1. tập tin tải lên (sử dụng kẹp giấy để S3/db trên Heroku). Tệp cần phải riêng tư vì tệp chứa dữ liệu nhạy cảm. tập tin
  2. Queue để chế biến (trì hoãn công việc)
  3. Job được chạy trong hàng đợi
  4. tập tin được lấy ra (từ s3/db), và xử lý hoàn tất
  5. tập tin bị xóa (từ s3/db)

Vì tôi đang sử dụng công việc bị trì hoãn, tôi phải quyết định lưu trữ tệp trong cơ sở dữ liệu hoặc trên s3. Tôi giả định rằng việc lưu trữ các tập tin trên máy chủ web là ra khỏi câu hỏi như tôi đang sử dụng heroku và công việc bị trì hoãn. Tải tệp lên s3 mất nhiều thời gian. Tuy nhiên, lưu trữ các tệp trong db là tốn kém hơn. Lý tưởng nhất, chúng tôi muốn xử lý để hoàn thành càng nhanh càng tốt.

Mẫu thiết kế phổ biến hơn là gì? Lưu trữ tệp trên s3? Lưu trữ tệp trong db? Bất kỳ đá quý được đề nghị cụ thể được sử dụng để lấy và xử lý các tệp được lưu trữ trong s3 (aws-s3? S3?)?

Trả lời

4

Heroku có thời gian chờ là 30 giây trên bất kỳ yêu cầu nào của máy chủ (đã học được cách cứng), vì vậy, lưu trữ các tệp trên s3 chắc chắn là điều bắt buộc.

Hãy thử carrierwave (carrierwave railscasts) thay vì kẹp giấy, như tôi thích những người giúp đỡ thêm rằng đi trên tàu, cộng với có một số plugin tuyệt vời, như carrierwave_direct để tải các file lớn để S3, trong đó tích hợp độc đáo với carrierwave.

Delayed_job (railscasts - delayed_job) sẽ hoạt động tốt để xóa tệp khỏi s3 và bất kỳ quá trình xử lý nền nào khác có thể được yêu cầu.

tập đá quý của tôi bao gồm những điều sau đây:

gem 'delayed_job' 

gem "aws-s3", :require => 'aws/s3' 

gem 'fog' 

gem 'carrierwave' 

gem 'carrierwave_direct' 

sương mù đá quý là một cách tốt đẹp để có tất cả các thông tin tài khoản của bạn ở một nơi duy nhất và thiết lập tất cả mọi thứ khá độc đáo. Đối với đá quý AWS how-to, tài nguyên tốt.

Đây là một bộ điều khiển mẫu khi nộp một mẫu đơn để tải lên (có những cách chắc chắn tốt hơn để làm điều này, nhưng đối với mục đích minh họa)

def create 
    @asset = Asset.new(:description => params[:description], :user_id => session[:id], :question_id => @question.id) 
    if @asset.save && @asset.update_attributes(:file_name => sanitize_filename(params[:uploadfile].original_filename, @asset.id)) 
     AWS::S3::S3Object.store(sanitize_filename(params[:uploadfile].original_filename, @asset.id), params[:uploadfile].read, 'bucket_name', :access => :private, :content_type => params[:uploadfile].content_type) 
      if object.content_length.to_i < @question.emailatt.to_i.megabytes && object.content_length.to_i < 5.megabytes 
       url = AWS::S3::S3Object.url_for(sanitize_filename(params[:uploadfile].original_filename, @asset.id), 'bucket_name') 
       if @asset.update_attributes(:download_link => 1) 
        if Usermailer.delay({:run_at => 5.minutes.from_now}).attachment_user_mailer_download_notification(@asset, @question) 
         process_attachment_user_mailer_download(params[:uploadfile], @asset.id, 24.hours.from_now, @question.id) 
         flash[:notice] = "Thank you for the upload, we will notify this posts author" 
        end 
       end 
      end 
    else 
     @asset.destroy 
     flash[:notice] = "There was an error in processing your upload, please try again" 
     redirect_to(:controller => "questions", :action => "show", :id => @question.id) 
    end 
end 


private 

    def sanitize_filename(file_name, id) 
     just_filename = File.basename(file_name) 
     just_filename.sub(/[^\w\.\-]/,'_') 
     new_id = id.to_s 
     new_filename = "#{new_id}" + just_filename 
    end 

    def delete_process(uploadfile, asset_id, time, question_id) 
     asset = Asset.find(:first, :conditions => ["id = ?", asset_id]) 
     if delete_file(uploadfile, asset_id, time) && asset.destroy 
      redirect_to(:controller => "questions", :action => "show", :id => question_id) 
     end 
    end 


def process_attachment_user_mailer_download(uploadfile, asset_id, time, question_id) 
     asset = Asset.find(:first, :conditions => ["id = ?", asset_id]) 
     if delete_file(uploadfile, asset_id, time) && @asset.delay({:run_at => time}).update_attributes(:download_link => 0) 
      redirect_to(:controller => "questions", :action => "show", :id => question_id) 
     end 
    end 

    #S3 METHODS FOR CREATE ACTION 

    #deletes the uploaded file from s3 
    def delete_file(uploadfile, asset_id, time) 
     AWS::S3::S3Object.delay({:run_at => time}).delete(sanitize_filename(uploadfile.original_filename, asset_id), 'bucket_name') 
    end 

Rất nhiều mã không cần thiết, tôi biết (viết này khi tôi đã bắt đầu với Rails). Hy vọng rằng nó sẽ cung cấp cho một số ý tưởng về các quy trình liên quan đến việc viết loại ứng dụng này. Hy vọng nó giúp.

3

Về phần tôi, tôi đang sử dụng:

  • Delayed Job
  • Paperclip
  • Delayed Paperclip đó tải lên các tập tin gốc trên S3 và tạo ra một công việc trì hoãn với bài tùy chỉnh xử lý. Nó có thể thêm một cột vào mô hình của bạn cho biết rằng tệp đang được xử lý .

Chỉ một vài dòng để thiết lập. Và bạn có thể làm rất nhiều với nội suy và máy phát giấy.