30Dec/090
Ruby File extensions: Mime types, encodings, file extensions list, mime detection, OH ME OH MY
This is my file class in ruby. I like knowing real file extensions of files that are being uploaded. I'm not keen on trusting the extension that comes with the file. So I wrote this little extension to the file class to get all sorts of mime related data from the file using the 'file' command line utility. Make sure you install that for your operating system of choice. Gives you things like all possible extensions for a given mime type, media type, sub type, and can even correct incorrect or missing extensions.
This uses the mime/types rubygem for getting a list of extensions. Install that first:
1 | gem install mime-types |
Put this in your core ext somewhere:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | require "rubygems" require "mime/types" require "open3" class File attr_reader :mime_type, :media_type, :sub_type, :encoding, :extensions def extensions self.mime if @extensions.nil? @extensions end def encoding self.mime if @encoding.nil? @encoding end def sub_type self.mime if @sub_type.nil? @sub_type end def media_type self.mime if @media_type.nil? @media_type end def mime_type self.mime if @mime_type.nil? @mime_type end def mime if @mime_type.nil? @mime_type = File.sys_file_cmd(File.expand_path(self.path)) unless @mime_type.nil? type = MIME::Types[@mime_type].first @media_type = type.media_type if type @sub_type = type.sub_type if type @encoding = type.encoding if type @extensions = type.extensions if type end end return @mime_type end def File.mime(path) File.sys_file_cmd(path) end def correct_extension! File.correct_extension!(self.path) end =begin rdoc *Name*:: File.correct_extension! *Access*:: public, static *Description*:: Corrects a files extension *Authors*:: Cory ODaniel *Last_Edited*:: Wed Feb 13 12:04:11 PST 2008 ===Parameters * Name: file_path * Description: Path to file * Datatype: String * Default: None * Required: True ===Returns *Description*:: Path to new file or FALSE *Datatype*:: String | False =end def File.correct_extension!(file_path) extensions = MIME::Types[File.mime(file_path)][0].extensions return false if extensions.nil? extension = File.extname(file_path) unless extensions.include?(extension) directory = File.dirname(file_path) file_name = File.basename(file_path).split(".") file_name.pop if file_name.size > 1 #Remove the bad extension file_name.push(extensions.first) #just user the first extension in list file_name = file_name.join(".") begin new_path = File.join(directory,file_name) File.rename(file_path,new_path) return new_path rescue Exception => e return false end end end private =begin rdoc *Name*:: File.sys_file_cmd *Access*:: private, static *Description*:: Handles call to system "file" command *Authors*:: Cory ODaniel *Last_Edited*:: Wed Feb 13 12:13:39 PST 2008 ===Parameters * Name: path * Description: file to get mime info for * Datatype: String * Default: None * Required: True ===Returns *Description*:: Mime information *Datatype*:: String | nil =end def File.sys_file_cmd(path) if File.exist? path stdin,stdout,stderr = Open3.popen3(%{file --mime -b #{path}}) file_err = stderr.gets file_out = stdout.gets if file_err raise Exception, "The 'file' command line binary was not found." end if file_err.nil? && (!file_out.nil? && !file_out.empty?) return file_out.split(";")[0].strip end end return nil end end |
Wanna use it?
1 2 3 4 5 6 7 8 9 10 11 12 13 | # load the file from above however you wanna do it File.mime("path/to/your/file.html") => "text/html" @f = File.open("path/to/your/file.html") @f.mime #=> "text/html" @f.extensions #=> ['html', 'htm'] @f.media_type #=> "text" @f.sub_type #=> "html" @wrong_extension = File.open("path/to/image/with/wrong.extension") @wrong_extension.correct_extension! # Or as a class method File.correct_extension!("path/to/a/file/with/a/wrong.extension") |
Yay, youve got correct extensions. Congrats.