2010-03-26 25 views
37

Me gustaría poder leer un archivo XML subido por el usuario (menos de 100kb), pero no tener que guardar primero ese archivo en la base de datos . No necesito ese archivo más allá de la acción actual (sus contenidos se analizan y se agregan a la base de datos, sin embargo, analizar el archivo no es el problema). Dado que los archivos locales se pueden leer con:cómo leer un archivo subido por el usuario, sin guardarlo en la base de datos

File.read("export.opml") 

pensaba sólo la creación de un file_field para: uploaded_file, a continuación, tratando de leer con

File.read(params[:uploaded_file]) 

pero todo lo que hace es lanzar una TypeError (puede' t convierte HashWithIndifferentAccess en String). Realmente he intentado muchas cosas (incluida la lectura del directorio/tmp también), pero no conseguí que ninguna de ellas funcionara.

Espero que la brevedad de mi pregunta no enmascare el esfuerzo que he dado para tratar de resolver esto por mi cuenta, pero no quería contaminar esta pregunta con cientos de maneras de cómo NO obtenerla hecho. . Muchas gracias a todo el que interviene

Aquí está mi punto de vista:

<% 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 %> 

I fijó una acción personalizada (carga), que gestiona la carga file_field, que después de la presentación, se pasa a otra acción personalizada (análisis) para el procesamiento. ¿Podría ser esto parte de mi problema?

Respuesta

43

Estás muy cerca. Compruebe el tipo de clase de params[:uploaded_file], normalmente debe ser un objeto StringIO o Tempfile, que ya actúan como archivos y se pueden leer con sus respectivos métodos read.

sólo para estar seguro (el tipo de clase de params[:uploaded_file] puede variar dependiendo de si se está utilizando Mestizo, Pasajero, WEBrick etc.) se puede hacer un poco más exhaustiva intento:

# 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 

Si, en su caso, resulta que params[:uploaded_file] es un hash, asegúrese de no haber volteado erróneamente los parámetros object_name y method al invocar file_field en su vista, o que su servidor no le está dando un hash con claves como :content_type etc. (en las cuales caso, por favor comente en esta publicación con la salida Bad file_data ... de development.log/production.log.)

+0

Hola Vlad! Gracias por su respuesta. No estaba exactamente seguro de cómo usar tu código. Cuando analizo, llamo file_data o xml_contents de alguna manera. Como si acabara de configurar xml = Archivo.read (params [: upfile]) luego analizo (xml) Entonces, no estaba seguro, pero no era para detenerme allí, intenté algunas cosas diferentes. Intenté usar tanto Webrick como Thin para ver si los resultados eran los mismos ... lo eran. Cuando uso File.read (params [: upfile]), obtengo un "no se puede convertir HashWithIndifferentAccess en String" ¿Podría ser que el upfile comience a pasar? "archivo_cargado" => {"archivo_cargado" => # GoodGets

+0

Cuando trato de usar la ruta xml = File.read (params [: upfile] .path) Me sale un mensaje indefinido Método 'ruta' ¿Podría haber algún problema con mi "vista"? He editado mi pregunta anterior para incluirla. – GoodGets

+0

He estado jugando con mi Vista. Ahora estoy usando: <% form_for: feed,: url => {: controller => 'feeds',: action => 'parse'} do | f | %> y cuando ahora envío el archivo cargado, obtengo un TypeError "no se puede convertir nada en String" Por lo tanto, creo que algo no se está transfiriendo correctamente. – GoodGets

6

Necesito leer archivos yaml. Yo uso remotipart y aquí el código:

en html.slim

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

...

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

en el controlador

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