Starkers
Starkers

Reputation: 10551

Reading and writing file attributes

In the rails console:

ActionDispatch::Http::UploadedFile.new tempfile: 'tempfilefoo', original_filename: 'filename_foo.jpg', content_type: 'content_type_foo', headers: 'headers_foo'
 => #<ActionDispatch::Http::UploadedFile:0x0000000548f3a0 @tempfile="tempfilefoo", @original_filename=nil, @content_type=nil, @headers=nil> 

I can write a string to @tempfile, and yet @original_filename, @content_type and @headers remain as nil

Why is this and how can I write information to these attributes?

And how can I read these attributes from a file instance?

i.e.

File.new('path/to/file.png')

Upvotes: 3

Views: 3296

Answers (2)

Jordan Running
Jordan Running

Reputation: 106077

It's not documented (and doesn't make much sense), but it looks like the options UploadedFile#initialize takes are :tempfile, :filename, :type and :head:

def initialize(hash) # :nodoc:
  @tempfile          = hash[:tempfile]
  raise(ArgumentError, ':tempfile is required') unless @tempfile

  @original_filename = encode_filename(hash[:filename])
  @content_type      = hash[:type]
  @headers           = hash[:head]
end

Changing your invocation to this ought to work:

ActionDispatch::Http::UploadedFile.new tempfile: 'tempfilefoo',
  filename: 'filename_foo.jpg', type: 'content_type_foo', head: 'headers_foo'

Or you can set them after initialization:

file = ActionDispatch::Http::UploadedFile.new tempfile: 'tempfilefoo', filename: 'filename_foo.jpg'
file.content_type = 'content_type_foo'
file.headers = 'headers_foo'

I'm not sure I understand your second question, "And how can I read these attributes from a file instance?"

You can extract the filename (or last component) from any path with File.basename:

file = File.new('path/to/file.png')
File.basename(file.path) # => "file.png"

If you want to get the Content-Type that corresponds to a file extension, you can use Rails' Mime module:

type = Mime["png"] # => #<Mime::Type:... @synonyms=[], @symbol=:png, @string="text/png">
type.to_s          # => "text/png"

You can put this together with File.extname, which gives you the extension:

ext = File.extname("path/to/file.png") # => ".png"
ext = ext.sub(/^\./, '') # => "png" (drop the leading dot)
Mime[ext].to_s           # => "text/png"

You can see a list of all of the MIME types Rails knows about by typing Mime::SET in the Rails console, or looking at the source, which also shows you how to register other MIME types in case you're expecting other types of files.

Upvotes: 3

Harsh Trivedi
Harsh Trivedi

Reputation: 1624

the following should help you:

upload = ActionDispatch::Http::UploadedFile.new({ 
    :tempfile => File.new("#{Rails.root}/relative_path/to/tempfilefoo") , #make sure this file exists
    :filename => "filename_foo" # use this instead of original_filename 
})
upload.headers = "headers_foo"
upload.content_type = "content_type_foo"

I didn't understand by "And how can I read these attributes from a file instance?", what you exactly want to do. Perhaps if you want to read the tempfile, you can use:

upload.read # -> content of tempfile
upload.rewind # -> rewinds the pointer back so that you can read it again.

Hope it helps :) And let me know if I have misunderstood.

Upvotes: 2

Related Questions