Почему Net :: HTTP перестает работать, когда я пытаюсь получить доступ к PDF-файлам, созданным креветками? - PullRequest
2 голосов
/ 14 декабря 2011

Я использую Prawn для создания PDF из моего контроллера, и при прямом доступе к URL-адресу он работает без сбоев, IE localhost: 3000 / response / 1.pdf

Однако, когда я пытаюсь сгенерироватьэтот файл на лету для включения в почтовую программу, все зависает и время ожидания истекает.

Я пробовал различные способы создания / прикрепления файла, и ни один из них не изменил результат.

Iтакже пытался изменить время ожидания для Net :: HTTP, но безрезультатно, просто требуется больше времени для LONGER.

Если я запускаю эту команду на консоли Rails, я получаю поток данных PDF.

Net::HTTP.get('127.0.0.1',"/responses/1.pdf", 3000)

Но если я включу этот код в свой контроллер, он истечет.

Я попробовал два разных метода, и оба неоднократно терпели неудачу.

Метод 1 Контроллер:

http = Net::HTTP.new('localhost', 3000)
http.read_timeout = 6000
file = http.get(response_path(@response, :format => 'pdf')) #timeout here
ResponseMailer.confirmComplete(@response,file).deliver #deliver the mail!

Метод 1 Mailer:

def confirmComplete(response,file)
  email_address = response.supervisor_id
  attachments["test.pdf"] = {:mime_type => "application/pdf", :content=> file}
  mail to: email_address, subject: 'Thank you for your feedback!'
end

Время действия приведенного выше кода истекло.

Метод 2 Контроллер:

ResponseMailer.confirmComplete(@response).deliver #deliver the mail!

Метод 2 Mailer:

def confirmComplete(response)
email_address = response.supervisor_id
attachment "application/pdf" do |a|
    a.body = Net::HTTP.get('127.0.0.1',"/responses/1.pdf", 3000) #timeout here
    a.filename = "test.pdf" 
end
mail to: email_address, subject: 'Thank you for your feedback!'

end

Если я переключаю a.body и a.filename, он сначала выдает ошибку с

undefined method `filename=' for #<Mail::Part:0x007ff620e05678>

Каждый найденный пример имеет другой синтаксис илипредложение, но никто не решает проблему, что Net :: HTTP истекает.Rails 3.1, Ruby 1.9.2

Ответы [ 2 ]

2 голосов
/ 15 декабря 2011

Проблема в том, что в процессе разработки вы запускаете только один серверный процесс, который занят созданием электронной почты.Этот процесс отправляет другой запрос (самому себе) для создания PDF и ждет ответа.Запрос на PDF в основном стоит в очереди на сервере, чтобы он мог получить его PDF, но сервер занят созданием электронной почты и ожидает получения PDF, прежде чем он может закончиться.И, таким образом, вы ждете вечно.

Что вам нужно сделать, это запустить второй серверный процесс ...

script/rails server -p 3001

, а затем получить свой PDF с чем-то вроде ...

args = ['127.0.0.1','/responses/1.pdf']
args << 3001 unless Rails.env == 'production'
file = Net::HTTP.get(*args)

Кроме того, в зависимости от того, какой сервер вы используете на своей рабочей машине, у вас могут возникнуть проблемы с указанием на 127.0.0.1.Возможно, вам придется сделать это динамическим и указывать на весь домен, когда вы работаете, но это должно быть легко.

1 голос
/ 15 декабря 2011

Я согласен с https://stackoverflow.com/users/811172/jon-garvin's анализом, что вы запускаете только один серверный процесс, но я бы упомянул другое решение.Рефакторинг генерации PDF, чтобы вы не зависели от вашего контроллера.

Если вы используете Prawnto , я полагаю, у вас есть вид, подобный

# app/views/response.pdf.prawn
pdf.text "Hello world"

Переместите это к вашей Response модели: (или куда-нибудь еще более подходящему, например, к докладчику)

# app/models/response.rb
require 'tmpdir'
class Response < ActiveRecord::Base
  def pdf_path
    return @pdf_path if @pdf_generated == true
    @pdf_path = File.join(Dir.tmpdir, rand(1e11).to_s)
    Prawn::Document.generate(@pdf_path) do |pdf|
      pdf.text "Hello world"
    end
    @pdf_generated = true
    @pdf_path
  end

  def pdf_cleanup
    if @pdf_generated and File.exist?(@pdf_path.to_s)
      File.unlink @pdf_path
    end
  end
end

Тогда в вашем ResponsesController вы можете сделать:

# app/controllers/responses_controller.rb
def show
  @response = Response.find params[:id]
  respond_to do |format|
    # this sends the PDF to the browser (doesn't email it)
    format.pdf { send_file @response.pdf_path, :type => 'application/pdf', :disposition => 'attachment', :filename => 'test.pdf' }
  end
end

Ив своей почтовой программе вы можете сделать:

# this sends an email with the PDF attached
def confirm_complete(response)
  email_address = response.supervisor_id
  attachments['test.pdf'] = {:mime_type => "application/pdf", :content => File.read(response.pdf_path, :binmode => true) }
  mail to: email_address, subject: 'Thank you for your feedback!'
end

Поскольку вы создали его в tmpdir, он будет автоматически удален при перезапуске вашего сервера.Вы также можете вызвать функцию очистки.

И последнее замечание: вы можете использовать другое название модели, например SupervisorReport или что-то еще - Response может привести к проблемам с пространством имен позже)

...