我有一個Heroku服務器上的文件上傳問題。 (另外一個暗示正確的方式做這種類型的東西與鐵路將不勝感激 - 我在RoR是非常新的)。Rails文件上傳和Heroku
所有這些代碼是關於上傳一些CSV文件,然後允許用戶調整幾個設置,並解析文件畢竟。這通常在本地主機上工作(有幾次,我會得到存儲在會話中的值的麻煩),但在Heroku上它總是死在上傳。
在附近的其中一個問題中,Heroku僅在單實例運行時才存儲文件,但在Heroku的文檔中仍然找不到關於此的任何內容。我應該在上傳後將文件數據存儲在數據庫中,因此在這種情況下,它始終可用?缺點 - 文件可能相當大,大約10-20Mb,看起來不太好。
Heroku的日誌說:
2012-05-21T19:27:20+00:00 app[web.1]: Started POST "/products/upload" for 46.119
.175.140 at 2012-05-21 19:27:20 +0000
2012-05-21T19:27:20+00:00 app[web.1]: Processing by ProductsController#upload
as HTML
2012-05-21T19:27:20+00:00 app[web.1]: Parameters: {"utf8"=>"тЬУ", "authenticit
y_token"=>"aqJFg3aqENfxS2lKCE4o4txxkZTJgPx36SZ7r3nyZBw=", "upload"=>{"my_file"=>
#<ActionDispatch::Http::UploadedFile:0x000000053af020 @original_filename="marina
-AutoPalmaPriceList_2011-07-30.txt", @content_type="text/plain", @headers="Conte
nt-Disposition: form-data; name=\"upload[my_file]\"; filename=\"marina-AutoPalma
PriceList_2011-07-30.txt\"\r\nContent-Type: text/plain\r\n", @tempfile=#<File:/t
mp/RackMultipart20120521-1-10g8xmx>>}, "commit"=>"Upload"}
2012-05-21T19:27:20+00:00 app[web.1]:
2012-05-21T19:27:20+00:00 app[web.1]: LoadError (no such file to load -- CSV):
2012-05-21T19:27:20+00:00 app[web.1]: app/controllers/products_controller.rb:8
2:in `upload'
2012-05-21T19:27:20+00:00 app[web.1]:
2012-05-21T19:27:20+00:00 app[web.1]:
2012-05-21T19:27:20+00:00 app[web.1]: cache: [POST /products/upload] invalidate,
pass
代碼本身:
的ProductsController:
def import
respond_to do |format|
format.html
end
end
def import_adjust
case params[:commit]
when "Adjust"
@col_default = params[:col_data]
#abort @col_default.to_yaml
#update csv reader with form data, restore filters from params
when "Complete"
#all ok, read the whole file
#abort params.to_yaml
redirect_to import_complete
else
@col_default = nil
end
#read first part of the file
@tmp = session[:import_file]
@csv = []
source = CSV.open @tmp, {col_sep: ";"}
5.times do
line = source.readline
if line.size>0
@line_size = line.size
@csv.push line
end
end
#generate a selection array
#selection = select_tag 'col_data[]', options_for_select([['name','name'], ['brand','brand'], ['delivery_time','delivery_time'], ['price','price']])
#@csv = [selection * line_size] + @csv
end
def import_complete
#remove all items
#todo check products with line items will not be destroyed.
Product.destroy_all
#abort params.to_yaml
map = {}
cnt = 0
#todo check for params count.
params[:col_data].each do |val|
map[cnt] = val if val != 'ignore'
cnt += 1
end
source = CSV.open session[:import_file], {col_sep: ';'}
source.each do |row|
cnt += 1
if row.size > 0
item = Product.new
map.each do |col, attr|
item[attr] = row[col]
end
item[:provider_id] = params[:adjust][:provider]
item.save
#abort item.to_yaml
end
end
#abort map.to_yaml
#todo response needed.
end
def upload
require 'CSV' #looks like I dont need this in fact.
@tmp = params[:upload][:my_file].path #tempfile
@csv = []
#source = CSV.open @tmp, {col_sep: ";"}
session[:import_file] = params[:upload][:my_file].path
respond_to do |format|
format.html { redirect_to action: 'import_adjust' }
end
end
upload.html.erb:
<h1>Uploaded</h1>
<%= @tmp %>
<% @csv.each do |val| %>
<%= val %>
<% end %>
_form_import.html.erb:
<%= form_for :upload, :html => {:multipart => true}, :url => {action: "upload"} do |f| %>
<%= f.file_field :my_file %>
<%= f.submit "Upload" %>
<% end %>
import_adjust.html.erb:
<h1>New product</h1>
<%= form_for :adjust, :url => {action: "import_adjust"} do |f| %>
<% if @csv %>
<table>
<tr>
<% @line_size.times do |cnt| %>
<td>
<%= select_tag 'col_data[]',
options_for_select([
['--ignore--', 'ignore'],
['name','name'],
['brand','brand'],
['delivery_time','delivery_time'],
['price','price']
], @col_default!=nil ? @col_default[cnt] : nil) %>
</td>
<% end %>
</tr>
<% @csv.each do |val| %>
<tr>
<% val.each do |cell| %>
<td>
<%= cell %>
</td>
<% end %>
</tr>
<% end %>
</table>
<% end %>
<%= f.label :delimiter, 'Разделитель' %>
<%= f.text_field :delimiter %>
<br>
<%= f.label :provider, 'Поставщик' %>
<%#todo default empty option needed! Human mistakes warning! %>
<%= f.select :provider, Provider.all.collect { |item| [item.name, item.id] } %>
<br>
<%= f.label :delimiter, 'Разделитель' %>
<%= f.text_field :delimiter %>
<br>
<%# Adjust for proceed adjusting or Complete for parsing %>
<%= f.submit "Adjust" %>
<%= f.submit "Complete" %>
<% end %>
<%= link_to 'Back', products_path %>
我稍後會發布完整的代碼。不同的臨時文件存儲不是這個項目的問題,但感謝您的提示。立即做所有的過程是很難的。網站應該允許用戶上傳文件,然後調整文件結構的幾件事情 - 換行符,分隔符等。在沒有附加服務器請求的情況下做這樣的事情看起來是不可能的。此外,看起來客戶不想使用S3(也許Heroku也是如此 - 現在它只是用於測試部署的最簡單的主機)。 – lifecoder
趕上吧!實際上,它確實在#82行(我自己錯過了這個日誌字符串),但它並沒有打開 - 它是「require'CSV'」。要求在* nix上區分大小寫,但在Windows上完全不敏感,所以我在localhost上錯過了這個問題。 – lifecoder