Как читать загруженный пользователем файл, не сохраняя его в базе данных
Я хотел бы иметь возможность читать XML файл, загруженный пользователем (менее 100 кб), но не нужно сначала сохранять этот файл в базе данных. Мне не нужен этот файл за текущим действием (его содержимое анализируется и добавляется в базу данных, однако разбор файла не является проблемой). Поскольку локальные файлы можно читать с помощью:
File.read("export.opml")
Я подумал о создании файла_файла для: uploaded_file, а затем попытался прочитать его с помощью
File.read(params[:uploaded_file])
но все, что делает, это throw 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 %>
Я настраиваю пользовательское действие (upload), которое обрабатывает загрузку file_field, которая после отправки передается другому пользовательскому действию (parse) для обработки. Может ли это быть частью моей проблемы?
Ответы
Ответ 1
Вы очень близки. Проверьте тип класса params[:uploaded_file]
, он обычно должен быть либо 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
и method
при вызове file_field
, или что ваш сервер не дает вам хэша с такими ключами, как :content_type
и т.д. (в этом случае прокомментируйте это сообщение с выводом Bad file_data ...
из development.log
/production.log
.)
Ответ 2
Мне нужно прочитать файлы 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)