【问题标题】:Rails - Roo "file does not exist" error when using Delayed JobRails - 使用延迟作业时出现 Roo“文件不存在”错误
【发布时间】:2013-05-16 15:11:57
【问题描述】:

我正在使用 Roo gem 导入 Excel 文件、CSV 文件等。

代码在我的本地机器上运行良好,无论是否有延迟作业,b)在 Heroku 上没有延迟作业。不幸的是,在 Heroku 上运行时,如果我使用延迟作业,它会失败。

这里是详细信息。

控制器:

def importdo
  fileimport = Fileimport.new
  fileimport.file_name = params[:file].original_filename
  fileimport.file_path = params[:file].path
  fileimport.save
  fileimportid = fileimport.id
  Building.delay.import(fileimportid)
  redirect_to buildings_path, notice: "Buildings import started . . . you will receive an email upon completion."
end

fileimport 只是我用来跟踪文件名和文件路径的表(我尝试将这些作为参数传递,但在尝试将哈希转换为 YAML 时,DelayedJob 总是会出现问题,所以我只是传入记录ID 代替)。这也让我可以在表格中跟踪我的导入。

这是我的导入类方法:

def self.import(fileimportid)
    fileimport = Fileimport.find(fileimportid)
    file_name = fileimport.file_name
    file_path = fileimport.file_path
    newcount = 0
    updatecount = 0
    updating = false
    Building.acts_as_gmappable :process_geocoding => false
    spreadsheet = open_spreadsheet(file_name, file_path)
    header = spreadsheet.row(1)
    (2..spreadsheet.last_row).each do |i|
        row = Hash[[header, spreadsheet.row(i)].transpose]

        if zip = row["zip"].to_i.to_s
            if zip.length > 5
                zip = zip.first(5)
            end
        else
            raise "zip not valid"
        end

        if building = find_by_address_and_zip(row["address"], zip)
            updating = true
        else
            building = Building.new
        end
        #building.name = row["name"]
        building.zip = zip
        building.address = row["address"]
        building.city = row["city"]
        building.save!
        if updating
            updatecount += 1
        else
            newcount += 1
        end
        updating=false
    end
    Building.acts_as_gmappable :process_geocoding => true

    subject = "Your Building Import Completed Successfully!"
    body = "Your Building Import completed successfully!\n\n" + newcount.to_s + " buildings were created.\n" + updatecount.to_s + " buildings were updated."

    require 'rest_client'

    RestClient.post MAILGUN_API_URL+"/messages", :from => "obfuscated", :to => "obfuscated", :subject => subject, :text => body 

end

def self.open_spreadsheet(file_name, file_path)
    case File.extname(file_name)
        when ".csv" then Roo::Csv.new(file_path, nil, :ignore)
        when ".xls" then Roo::Excel.new(file_path, nil, :ignore)
        when ".xlsx" then Roo::Excelx.new(file_path, nil, :ignore)
    else
        raise "Unknown file type: #{file_name}"
    end
end

这是我的文件输入表单:

<% provide(:title, 'Import Buildings') %>
<div class="row">
    <aside class="span4">
        <section>
            <h1>
                Import Products
            </h1>
            <%= form_tag importdo_buildings_path, multipart: true do %>
                <%= file_field_tag :file %>
                <%= submit_tag "Import" %>
            <% end %>
        </section>
    </aside>
</div>

路线如下:

resources :buildings do
    collection { post :importdo }
end

无论如何,就像我说的,在我的盒子上工作得很好(无论有没有延迟工作)。仅在 Heroku 上工作而不会延迟工作(即我必须取出 .delay)。这是我收到的具体错误(错误通过电子邮件发送给我,我使用观察者检查 Delayed::Job 何时保存记录并检查 last_error):

file /tmp/RackMultipart20130516-13-7li3o7 does not exist
/app/vendor/bundle/ruby/1.9.1/gems/roo-1.11.2/lib/roo/excel.rb:26:in `block in initialize'
/app/vendor/bundle/ruby/1.9.1/gems/roo-1.11.2/lib/roo/generic_spreadsheet.rb:579:in `block in make_tmpdir'
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/tmpdir.rb:83:in `mktmpdir'
/app/vendor/bundle/ruby/1.9.1/gems/roo-1.11.2/lib/roo/generic_spreadsheet.rb:578:in `make_tmpdir'
/app/vendor/bundle/ruby/1.9.1/gems/roo-1.11.2/lib/roo/excel.rb:19:in `initialize'
/app/app/models/building.rb:84:in `new'
/app/app/models/building.rb:84:in `open_spreadsheet'
/app/app/models/building.rb:39:in `import'

我最初的想法是它只是一个 Heroku 文件系统的东西,但后来我认为如果没有 delay_job 它也行不通。我的另一个想法是,因为它是异步的,所以可能是时间问题(可能临时文件不存在或不再存在)。

非常感谢任何想法。

【问题讨论】:

  • 我没有在 Heroku 上使用过 DJ,但我使用过 Resque ——而且我必须确保工作人员被调动起来。你有 dynos 旋转来处理延迟工作的工作吗?
  • 我正在使用无工作,并且 DelayedJob 正在运行,因为这就是给我错误的原因。我可以尝试关闭无工作人员,让工作人员做好准备,以防万一。

标签: ruby-on-rails heroku delayed-job import-from-excel


【解决方案1】:

您最初的想法是正确的。您的问题背后是 Heroku 文件系统。即只读规则!

当您将文件发送到 Heroku 时,它会存储在临时文件夹中,并且仅在此一次请求期间可用。它可以在没有延迟作业的情况下工作,因为您在一个请求期间完成您的工作并且文件可用。

但延迟作业是在请求结束时单独完成的,因此文件被删除。

最简单的解决方案是将文件放在一些云存储中(为此我使用了 S3 和carrierwave。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    • 2013-09-23
    • 2012-04-20
    • 1970-01-01
    • 2012-10-28
    相关资源
    最近更新 更多