web-dev-qa-db-ja.com

データベースに保存せずに、ユーザーがアップロードしたファイルを読み取る方法

ユーザーがアップロードしたXMLファイル(100 kb未満)を読みたいのですが、最初にそのファイルをデータベースに保存する必要はありません。現在のアクションを過ぎてそのファイルは必要ありません(その内容は解析されてデータベースに追加されますが、ファイルの解析は問題ではありません)。ローカルファイルは次の方法で読み取ることができるため、

File.read("export.opml")

:uploaded_fileのfile_fieldを作成してから、それを読み取ろうと考えました

File.read(params[:uploaded_file])

ただし、TypeErrorをスローするだけです(HashWithIndifferentAccessをStringに変換できません)。 (/ tmpディレクトリからの読み取りも含めて)さまざまなことを実際に試しましたが、どれも機能しませんでした。

私の質問の簡潔さが、これを自分で解決しようとする努力を隠さないことを願っていますが、私はこの質問を何百もの方法で終わらせない方法で汚染したくありませんでした。声をかけてくれた人に感謝します。

私の見解は次のとおりです。

<% form_for(:uploaded_file, @feed, :url => {:action=>'parse'}, :html=> {:multipart=>true}) do |f| %>  <p>
    <%= f.label :uploaded_file, 'Upload your file.' %><br />
    <%= f.file_field :uploaded_file %>
  </p>
  <p><%= f.submit 'upload' %></p>
<% end %>

File_fieldアップロードを処理するカスタムアクション(アップロード)を設定します。アップロードは、送信後、処理のために別のカスタムアクション(解析)に渡されます。これは私の問題の一部でしょうか?

41
GoodGets

あなたはとても近いです。 params[:uploaded_file]class typeを確認してください。通常は StringIO または Tempfile オブジェクト-両方とも既にファイルとして機能し、それぞれのreadメソッドを使用して読み取ることができます。

念のために(params[:uploaded_file]のクラスタイプは、Mongrel、Passenger、Webrickなどを使用しているかどうかによって異なる場合があります)、もう少し徹底的に試すことができます。

# Note: use form validation to ensure that
#  params[:uploaded_file] is not null

file_data = params[:uploaded_file]
if file_data.respond_to?(:read)
  xml_contents = file_data.read
elsif file_data.respond_to?(:path)
  xml_contents = File.read(file_data.path)
else
  logger.error "Bad file_data: #{file_data.class.name}: #{file_data.inspect}"
end

あなたの場合、params[:uploaded_file]がハッシュであることが判明した場合、ビューで object_name を呼び出すときにfile_fieldmethodパラメータを誤って反転していないこと、またはサーバーがあなたに与えていないことを確認してください:content_typeなどのキーを持つハッシュ(この場合、Bad file_data .../development.logからのproduction.log出力でこの投稿にコメントしてください)

47
vladr

Yamlファイルを読む必要があります。私はremotipartを使用し、ここでコード:

html.slim

 =form_tag('/locations/check_for_import', method: :post, remote: true, multipart: true)

...

<input id="uploadInput" type="file" name="uploadInput">

コントローラー内

content = File.read(params[:uploadInput].tempfile)
doc = YAML.load(content)
8
Ivan