contentful-importer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +38 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile +7 -0
  7. data/Gemfile.lock +87 -0
  8. data/LICENSE +22 -0
  9. data/README.md +327 -0
  10. data/Rakefile +7 -0
  11. data/bin/contentful-importer +85 -0
  12. data/contentful_importer.gemspec +38 -0
  13. data/example_settings/contentful_model.json +288 -0
  14. data/example_settings/contentful_structure.json +78 -0
  15. data/example_settings/files_meaning.txt +15 -0
  16. data/example_settings/settings.yml +16 -0
  17. data/lib/cli.rb +13 -0
  18. data/lib/configuration.rb +36 -0
  19. data/lib/converters/content_types_structure_creator.rb +60 -0
  20. data/lib/converters/contentful_model_to_json.rb +109 -0
  21. data/lib/importer/data_organizer.rb +117 -0
  22. data/lib/importer/mime_content_type.rb +564 -0
  23. data/lib/importer/parallel_importer.rb +429 -0
  24. data/lib/json_schema_validator.rb +64 -0
  25. data/lib/migrator.rb +39 -0
  26. data/lib/version.rb +3 -0
  27. data/spec/fixtures/import_files/assets/image/image_1.json +9 -0
  28. data/spec/fixtures/import_files/assets/image/image_2.json +9 -0
  29. data/spec/fixtures/import_files/assets/image/image_3.json +9 -0
  30. data/spec/fixtures/import_files/assets/image/image_4.json +9 -0
  31. data/spec/fixtures/import_files/collections/job_skills.json +13 -0
  32. data/spec/fixtures/import_files/collections/jobs.json +37 -0
  33. data/spec/fixtures/import_files/collections/profile.json +19 -0
  34. data/spec/fixtures/import_files/collections/user.json +36 -0
  35. data/spec/fixtures/import_files/entries/job_skills/job_skills_1.json +7 -0
  36. data/spec/fixtures/import_files/entries/job_skills/job_skills_10.json +7 -0
  37. data/spec/fixtures/import_files/entries/job_skills/job_skills_2.json +7 -0
  38. data/spec/fixtures/import_files/entries/job_skills/job_skills_3.json +7 -0
  39. data/spec/fixtures/import_files/entries/job_skills/job_skills_4.json +7 -0
  40. data/spec/fixtures/import_files/entries/job_skills/job_skills_5.json +7 -0
  41. data/spec/fixtures/import_files/entries/job_skills/job_skills_6.json +7 -0
  42. data/spec/fixtures/import_files/entries/job_skills/job_skills_7.json +7 -0
  43. data/spec/fixtures/import_files/entries/job_skills/job_skills_8.json +7 -0
  44. data/spec/fixtures/import_files/entries/job_skills/job_skills_9.json +7 -0
  45. data/spec/fixtures/import_files/entries/jobs/jobs_1.json +56 -0
  46. data/spec/fixtures/import_files/entries/jobs/jobs_2.json +55 -0
  47. data/spec/fixtures/import_files/entries/jobs/jobs_4.json +49 -0
  48. data/spec/fixtures/import_files/entries/profile/profile_1.json +12 -0
  49. data/spec/fixtures/import_files/entries/profile/profile_2.json +12 -0
  50. data/spec/fixtures/import_files/entries/user/user_1.json +24 -0
  51. data/spec/fixtures/import_files/entries/user/user_2.json +20 -0
  52. data/spec/fixtures/import_files/logs/log_published_assets.csv +4 -0
  53. data/spec/fixtures/import_files/logs/log_published_entries.csv +23 -0
  54. data/spec/fixtures/import_files/logs/success_assets.csv +4 -0
  55. data/spec/fixtures/import_files/logs/success_published_assets.csv +0 -0
  56. data/spec/fixtures/import_files/logs/success_published_entries.csv +22 -0
  57. data/spec/fixtures/import_files/logs/success_thread_0.csv +12 -0
  58. data/spec/fixtures/import_files/logs/success_thread_1.csv +11 -0
  59. data/spec/fixtures/import_files/threads/0/1TVvxCqoRq0qUYAOQuOqys_2.json +20 -0
  60. data/spec/fixtures/import_files/threads/0/2soCP557HGKoOOK0SqmMOm_1.json +7 -0
  61. data/spec/fixtures/import_files/threads/0/2soCP557HGKoOOK0SqmMOm_10.json +7 -0
  62. data/spec/fixtures/import_files/threads/0/2soCP557HGKoOOK0SqmMOm_2.json +7 -0
  63. data/spec/fixtures/import_files/threads/0/2soCP557HGKoOOK0SqmMOm_3.json +7 -0
  64. data/spec/fixtures/import_files/threads/0/2soCP557HGKoOOK0SqmMOm_4.json +7 -0
  65. data/spec/fixtures/import_files/threads/0/2soCP557HGKoOOK0SqmMOm_5.json +7 -0
  66. data/spec/fixtures/import_files/threads/0/2soCP557HGKoOOK0SqmMOm_6.json +7 -0
  67. data/spec/fixtures/import_files/threads/0/2soCP557HGKoOOK0SqmMOm_7.json +7 -0
  68. data/spec/fixtures/import_files/threads/0/6H6pGAV1PUsuoAW26Iu48W_1.json +9 -0
  69. data/spec/fixtures/import_files/threads/0/6H6pGAV1PUsuoAW26Iu48W_2.json +9 -0
  70. data/spec/fixtures/import_files/threads/0/6H6pGAV1PUsuoAW26Iu48W_3.json +9 -0
  71. data/spec/fixtures/import_files/threads/0/6H6pGAV1PUsuoAW26Iu48W_4.json +9 -0
  72. data/spec/fixtures/import_files/threads/0/6H6pGAV1PUsuoAW26Iu48W_5.json +9 -0
  73. data/spec/fixtures/import_files/threads/1/1TVvxCqoRq0qUYAOQuOqys_1.json +24 -0
  74. data/spec/fixtures/import_files/threads/1/1TVvxCqoRq0qUYAOQuOqys_2.json +20 -0
  75. data/spec/fixtures/import_files/threads/1/2soCP557HGKoOOK0SqmMOm_6.json +7 -0
  76. data/spec/fixtures/import_files/threads/1/2soCP557HGKoOOK0SqmMOm_7.json +7 -0
  77. data/spec/fixtures/import_files/threads/1/2soCP557HGKoOOK0SqmMOm_8.json +7 -0
  78. data/spec/fixtures/import_files/threads/1/2soCP557HGKoOOK0SqmMOm_9.json +7 -0
  79. data/spec/fixtures/import_files/threads/1/4L1bg4WQ5aWQMiE82ouag_1.json +56 -0
  80. data/spec/fixtures/import_files/threads/1/4L1bg4WQ5aWQMiE82ouag_2.json +55 -0
  81. data/spec/fixtures/import_files/threads/1/4L1bg4WQ5aWQMiE82ouag_4.json +49 -0
  82. data/spec/fixtures/import_files/threads/1/4WFZh4MwC4Mc0EQWAeOY8A_1.json +12 -0
  83. data/spec/fixtures/import_files/threads/1/4WFZh4MwC4Mc0EQWAeOY8A_2.json +12 -0
  84. data/spec/fixtures/import_files/threads/assets/0/image_1.json +9 -0
  85. data/spec/fixtures/import_files/threads/assets/0/image_2.json +9 -0
  86. data/spec/fixtures/import_files/threads/assets/0/image_3.json +9 -0
  87. data/spec/fixtures/import_files/threads/assets/0/image_4.json +9 -0
  88. data/spec/fixtures/settings/contentful_model.json +252 -0
  89. data/spec/fixtures/settings/contentful_structure.json +73 -0
  90. data/spec/fixtures/settings/contentful_structure_test.json +66 -0
  91. data/spec/fixtures/settings/settings.yml +12 -0
  92. data/spec/fixtures/vcr_cassettes/create_asset.yml +621 -0
  93. data/spec/fixtures/vcr_cassettes/create_entry.yml +122 -0
  94. data/spec/fixtures/vcr_cassettes/create_space.yml +87 -0
  95. data/spec/fixtures/vcr_cassettes/import_assets.yml +2822 -0
  96. data/spec/fixtures/vcr_cassettes/import_content_types.yml +1915 -0
  97. data/spec/fixtures/vcr_cassettes/import_entries.yml +5066 -0
  98. data/spec/fixtures/vcr_cassettes/import_entry.yml +363 -0
  99. data/spec/fixtures/vcr_cassettes/invalid_credentials.yml +69 -0
  100. data/spec/fixtures/vcr_cassettes/publish_an_entry.yml +214 -0
  101. data/spec/fixtures/vcr_cassettes/publish_asset.yml +895 -0
  102. data/spec/fixtures/vcr_cassettes/publish_entries.yml +5121 -0
  103. data/spec/fixtures/vcr_cassettes/valid_credentials.yml +7360 -0
  104. data/spec/lib/configuration_spec.rb +22 -0
  105. data/spec/lib/importer/parallel_importer_spec.rb +161 -0
  106. data/spec/lib/json_schema_validator_spec.rb +63 -0
  107. data/spec/lib/migrator_spec.rb +99 -0
  108. data/spec/spec_helper.rb +12 -0
  109. data/spec/support/db_rows_json.rb +9 -0
  110. data/spec/support/shared_configuration.rb +22 -0
  111. data/spec/support/vcr.rb +16 -0
  112. metadata +436 -0
@@ -0,0 +1,15 @@
1
+ 1. contentful_model.json
2
+
3
+ File which contains downloaded the entire structure of the Space.
4
+ To get this file use:
5
+ curl -X GET \
6
+ -H 'Authorization: Bearer ACCESS_TOKEN' \
7
+ 'https://api.contentful.com/spaces/SPACE_ID/content_types' > contentful_model.json
8
+
9
+ 2. contentful_structure.json
10
+
11
+ Contentful model structure converted to a form that importer supports.Contains models of content types with attributes and their types.
12
+
13
+ 3. settings.yml
14
+
15
+ Configuration file which contains defined paths to the files needed to export data.
@@ -0,0 +1,16 @@
1
+ #PATH to all data
2
+ data_dir: PATH_TO_ALL_DATA
3
+
4
+ ########## IMPORT DATA TO CONTENTFUL ##########
5
+
6
+ #Contentful credentials - Define before import data to Contentful.
7
+ access_token: ACCESS_TOKEN
8
+ organization_id: ORGANIZATION_ID
9
+ space_id: DEFINE_SPACE_ID_BEFORE_IMPORT
10
+ default_locale: LOCALE_CODE
11
+
12
+ ## CONVERT CONTENTFUL MODEL TO CONTENTFUL IMPORT STRUCTURE
13
+ content_model_json: example_settings/contentful_model.json
14
+ converted_model_dir: example_settings/contentful_structure.json
15
+
16
+ contentful_structure_dir: example_settings/contentful_structure.json
data/lib/cli.rb ADDED
@@ -0,0 +1,13 @@
1
+ require_relative 'migrator'
2
+ require 'yaml'
3
+
4
+ module Command
5
+ class CLI < Escort::ActionCommand::Base
6
+
7
+ def execute
8
+ setting_file = YAML.load_file(global_options[:file])
9
+ Migrator.new(setting_file).run(command_name, command_options)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,36 @@
1
+ require 'active_support/core_ext/hash'
2
+ module Contentful
3
+ class Configuration
4
+ attr_reader :space_id,
5
+ :config,
6
+ :data_dir,
7
+ :collections_dir,
8
+ :entries_dir,
9
+ :assets_dir,
10
+ :log_files_dir,
11
+ :threads_dir,
12
+ :imported_entries,
13
+ :published_entries,
14
+ :published_assets,
15
+ :space_id
16
+
17
+ def initialize(settings)
18
+ @config = settings
19
+ validate_required_parameters
20
+ @data_dir = settings['data_dir']
21
+ @collections_dir = "#{data_dir}/collections"
22
+ @entries_dir = "#{data_dir}/entries"
23
+ @assets_dir = "#{data_dir}/assets"
24
+ @log_files_dir = "#{data_dir}/logs"
25
+ @threads_dir = "#{data_dir}/threads"
26
+ @imported_entries = []
27
+ @published_entries = []
28
+ @published_assets = []
29
+ @space_id = settings['space_id']
30
+ end
31
+
32
+ def validate_required_parameters
33
+ fail ArgumentError, 'Set PATH to data_dir. Folder where all data will be stored. View README' if config['data_dir'].nil?
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,60 @@
1
+ module Contentful
2
+ module Converter
3
+ class ContentTypesStructureCreator
4
+
5
+ attr_reader :config, :logger
6
+
7
+ def initialize(config)
8
+ @config = config
9
+ @logger = Logger.new(STDOUT)
10
+ end
11
+
12
+ def create_content_type_json_file(content_type_name, values)
13
+ collection = {
14
+ id: values[:id],
15
+ name: values[:name],
16
+ description: values[:description],
17
+ displayField: values[:displayField],
18
+ fields: create_fields(values[:fields])
19
+ }
20
+ write_json_to_file("#{config.collections_dir}/#{content_type_name}.json", collection)
21
+ logger.info "Saving #{content_type_name}.json to #{config.collections_dir}"
22
+ end
23
+
24
+ def create_fields(fields)
25
+ fields.each_with_object([]) do |(field, value), results|
26
+ results << {
27
+ name: create_field(field, value).capitalize,
28
+ id: create_field(field, value),
29
+ type: create_type_field(value),
30
+ link_type: create_link_type_field(value),
31
+ link: create_link_field(value)
32
+ }.compact
33
+ end
34
+ end
35
+
36
+ def create_field(field, value)
37
+ value.is_a?(Hash) ? value[:id] : field
38
+ end
39
+
40
+ def create_link_type_field(value)
41
+ value.is_a?(Hash) ? value[:link_type] : nil
42
+ end
43
+
44
+ def create_type_field(value)
45
+ value.is_a?(Hash) ? value[:type] : value
46
+ end
47
+
48
+ def create_link_field(value)
49
+ value.is_a?(Hash) ? value[:link] : nil
50
+ end
51
+
52
+ def write_json_to_file(path, data)
53
+ File.open(path, 'w') do |file|
54
+ file.write(JSON.pretty_generate(data))
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,109 @@
1
+ require_relative 'content_types_structure_creator'
2
+
3
+ module Contentful
4
+ module Converter
5
+ class ContentfulModelToJson
6
+ attr_reader :config, :logger, :converted_model_dir, :content_types
7
+
8
+ FIELD_TYPE = %w( Link Array )
9
+
10
+ def initialize(settings)
11
+ @config = settings
12
+ @logger = Logger.new(STDOUT)
13
+ end
14
+
15
+ def create_content_type_json
16
+ contentful_structure = load_contentful_structure_file
17
+ logger.info 'Create JSON files with content types structure...'
18
+ contentful_structure.each do |content_type, values|
19
+ content_type_name = content_type_name(content_type)
20
+ create_directory(config.collections_dir)
21
+ ContentTypesStructureCreator.new(config).create_content_type_json_file(content_type_name, values)
22
+ end
23
+ logger.info 'Done!'
24
+ end
25
+
26
+ def convert_to_import_form
27
+ set_content_model_parameters
28
+ logger.info 'Converting Contentful model to Contentful import structure...'
29
+ File.open(converted_model_dir, 'w') { |file| file.write({}) }
30
+ content_type_file = JSON.parse(File.read(content_types))['items']
31
+ content_type_file.each do |content_type|
32
+ parsed_content_type = {
33
+ id: content_type['sys']['id'],
34
+ name: content_type['name'],
35
+ description: content_type['description'],
36
+ displayField: content_type['displayField'],
37
+ fields: create_content_type_fields(content_type)
38
+ }
39
+ import_form = JSON.parse(File.read(converted_model_dir))
40
+ File.open(converted_model_dir, 'w') do |file|
41
+ file.write(JSON.pretty_generate(import_form.merge!(content_type['name'] => parsed_content_type)))
42
+ end
43
+ end
44
+ logger.info "Done! Contentful import structure file saved in #{converted_model_dir}"
45
+ end
46
+
47
+ def create_content_type_fields(content_type)
48
+ content_type['fields'].each_with_object({}) do |(field, _value), results|
49
+ id = link_id(field)
50
+ results[id] = case field['type']
51
+ when 'Link'
52
+ {id: field['id'], type: field['linkType'], link: 'Link'}
53
+ when 'Array'
54
+ {id: field['id'], type: field['type'], link_type: field['items']['linkType'], link: field['items']['type']}
55
+ else
56
+ field['type']
57
+ end
58
+ end
59
+ end
60
+
61
+ def link_id(field)
62
+ if FIELD_TYPE.include? field['type']
63
+ field['name'].capitalize
64
+ else
65
+ field['id']
66
+ end
67
+ end
68
+
69
+ def content_type_name(content_type)
70
+ I18n.transliterate(content_type).underscore.tr(' ', '_')
71
+ end
72
+
73
+ def create_directory(path)
74
+ FileUtils.mkdir_p(path) unless File.directory?(path)
75
+ end
76
+
77
+ # If contentful_structure JSON file exists, it will load the file. If not, it will automatically create an empty file.
78
+ # This file is required to convert contentful model to contentful import structure.
79
+ def load_contentful_structure_file
80
+ fail ArgumentError, 'Set PATH for contentful structure JSON file. View README' if config.config['contentful_structure_dir'].nil?
81
+ file_exists? ? load_existing_contentful_structure_file : create_empty_contentful_structure_file
82
+ end
83
+
84
+ def file_exists?
85
+ File.exists?(config.config['contentful_structure_dir'])
86
+ end
87
+
88
+ def create_empty_contentful_structure_file
89
+ File.open(config.config['contentful_structure_dir'], 'w') { |file| file.write({}) }
90
+ load_existing_contentful_structure_file
91
+ end
92
+
93
+ def load_existing_contentful_structure_file
94
+ JSON.parse(File.read(config.config['contentful_structure_dir']), symbolize_names: true).with_indifferent_access
95
+ end
96
+
97
+ def set_content_model_parameters
98
+ validate_content_model_files
99
+ @converted_model_dir = config.config['converted_model_dir']
100
+ @content_types = config.config['content_model_json']
101
+ end
102
+
103
+ def validate_content_model_files
104
+ fail ArgumentError, 'Set PATH for content model JSON file. View README' if config.config['content_model_json'].nil?
105
+ fail ArgumentError, 'Set PATH where converted content model file will be saved. View README' if config.config['converted_model_dir'].nil?
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,117 @@
1
+ require 'fileutils'
2
+ require 'thread'
3
+ require_relative 'parallel_importer'
4
+
5
+ module Contentful
6
+ class DataOrganizer
7
+
8
+ attr_reader :config, :split_params, :logger
9
+
10
+ def initialize(settings)
11
+ @config = settings
12
+ @split_params = {object_index: 0, current_thread: 0}
13
+ @logger = Logger.new(STDOUT)
14
+ end
15
+
16
+ def execute(threads_count)
17
+ create_threads_subdirectories(threads_count, true)
18
+ split_entries(threads_count)
19
+ end
20
+
21
+ def split_assets_to_threads(threads_count)
22
+ create_threads_subdirectories(threads_count, false, {assets: 'assets/'})
23
+ split_assets(threads_count)
24
+ end
25
+
26
+ def split_entries(threads_count)
27
+ entries_per_thread_count = total_entries_count / threads_count
28
+ Dir.glob("#{config.entries_dir}/*") do |dir_path|
29
+ collection_name = File.basename(dir_path)
30
+ if has_contentful_structure?(collection_name)
31
+ content_type_id = content_type_id_from_file(collection_name)
32
+ process_collection_files(content_type_id, dir_path, entries_per_thread_count, threads_count)
33
+ end
34
+ end
35
+ end
36
+
37
+ def split_assets(threads_count)
38
+ asset_per_thread = total_assets_count / threads_count
39
+ Dir.glob("#{config.assets_dir}/**/*json") do |asset_path|
40
+ copy_asset(asset_path)
41
+ split_params[:object_index] += 1
42
+ count_index_files(asset_per_thread, threads_count)
43
+ end
44
+ end
45
+
46
+ def process_collection_files(content_type_id, dir_path, entries_per_thread_count, threads_count)
47
+ logger.info "Processing collection: #{content_type_id}"
48
+ Dir.glob("#{dir_path}/*.json") do |entry_path|
49
+ copy_entry(entry_path, split_params[:current_thread], content_type_id)
50
+ split_params[:object_index] += 1
51
+ count_index_files(entries_per_thread_count, threads_count)
52
+ end
53
+ end
54
+
55
+ def count_index_files(objects_per_thread_count, threads_count)
56
+ if split_params[:object_index] == objects_per_thread_count
57
+ split_params[:object_index] = 0
58
+ set_current_thread(threads_count)
59
+ end
60
+ end
61
+
62
+ def set_current_thread(threads_count)
63
+ split_params[:current_thread] += 1
64
+ split_params[:current_thread] = 0 if split_params[:current_thread] == threads_count
65
+ end
66
+
67
+ def has_contentful_structure?(collection_file)
68
+ File.exist?("#{config.collections_dir}/#{collection_file}.json")
69
+ end
70
+
71
+ def content_type_id_from_file(collection_file)
72
+ JSON.parse(File.read("#{config.collections_dir}/#{collection_file}.json"))['id']
73
+ end
74
+
75
+ def new_entry_name(content_type_id, entry_path)
76
+ "#{content_type_id}_#{File.basename(entry_path, '.*').match(/(\d+)/)[0]}.json"
77
+ end
78
+
79
+ def copy_entry(entry_path, current_thread, content_type_id)
80
+ FileUtils.cp entry_path, "#{config.threads_dir}/#{current_thread}/#{new_entry_name(content_type_id, entry_path)}"
81
+ end
82
+
83
+ def copy_asset(asset_path)
84
+ FileUtils.cp asset_path, "#{config.threads_dir}/assets/#{split_params[:current_thread]}/#{File.basename(asset_path)}"
85
+ end
86
+
87
+ def create_threads_subdirectories(threads_count, validate, dir = {})
88
+ validate_collections_files if validate
89
+ create_directory(config.threads_dir)
90
+ threads_count.times do |thread_id|
91
+ create_directory("#{config.threads_dir}/#{dir[:assets]}#{thread_id}")
92
+ end
93
+ end
94
+
95
+ def create_directory(path)
96
+ FileUtils.mkdir_p(path) unless File.directory?(path)
97
+ end
98
+
99
+ def total_entries_count
100
+ total_number = 0
101
+ Dir.glob("#{config.entries_dir}/*") do |dir_path|
102
+ collection_name = File.basename(dir_path)
103
+ total_number += Dir.glob("#{config.entries_dir}/#{collection_name}/*").count if has_contentful_structure?(collection_name)
104
+ end
105
+ total_number
106
+ end
107
+
108
+ def total_assets_count
109
+ Dir.glob("#{config.assets_dir}/**/*json").count
110
+ end
111
+
112
+ def validate_collections_files
113
+ fail ArgumentError, "Make sure the #{config.collections_dir} directory exists and the content structure resides within it. View README" unless Dir.exist?(config.collections_dir)
114
+ fail ArgumentError, 'Collections directory is empty! Create content types JSON files. View README' if Dir.glob("#{config.collections_dir}/*").empty?
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,564 @@
1
+ module Contentful
2
+ class MimeContentType
3
+ EXTENSION_LIST = {'.323' => 'text/h323',
4
+ '.3g2' => 'video/3gpp2',
5
+ '.3gp' => 'video/3gpp',
6
+ '.3gp2' => 'video/3gpp2',
7
+ '.3gpp' => 'video/3gpp',
8
+ '.7z' => 'application/x-7z-compressed',
9
+ '.aa' => 'audio/audible',
10
+ '.AAC' => 'audio/aac',
11
+ '.aaf' => 'application/octet-stream',
12
+ '.aax' => 'audio/vnd.audible.aax',
13
+ '.ac3' => 'audio/ac3',
14
+ '.aca' => 'application/octet-stream',
15
+ '.accda' => 'application/msaccess.addin',
16
+ '.accdb' => 'application/msaccess',
17
+ '.accdc' => 'application/msaccess.cab',
18
+ '.accde' => 'application/msaccess',
19
+ '.accdr' => 'application/msaccess.runtime',
20
+ '.accdt' => 'application/msaccess',
21
+ '.accdw' => 'application/msaccess.webapplication',
22
+ '.accft' => 'application/msaccess.ftemplate',
23
+ '.acx' => 'application/internet-property-stream',
24
+ '.AddIn' => 'text/xml',
25
+ '.ade' => 'application/msaccess',
26
+ '.adobebridge' => 'application/x-bridge-url',
27
+ '.adp' => 'application/msaccess',
28
+ '.ADT' => 'audio/vnd.dlna.adts',
29
+ '.ADTS' => 'audio/aac',
30
+ '.afm' => 'application/octet-stream',
31
+ '.ai' => 'application/postscript',
32
+ '.aif' => 'audio/x-aiff',
33
+ '.aifc' => 'audio/aiff',
34
+ '.aiff' => 'audio/aiff',
35
+ '.air' => 'application/vnd.adobe.air-application-installer-package+zip',
36
+ '.amc' => 'application/x-mpeg',
37
+ '.application' => 'application/x-ms-application',
38
+ '.art' => 'image/x-jg',
39
+ '.asa' => 'application/xml',
40
+ '.asax' => 'application/xml',
41
+ '.ascx' => 'application/xml',
42
+ '.asd' => 'application/octet-stream',
43
+ '.asf' => 'video/x-ms-asf',
44
+ '.ashx' => 'application/xml',
45
+ '.asi' => 'application/octet-stream',
46
+ '.asm' => 'text/plain',
47
+ '.asmx' => 'application/xml',
48
+ '.aspx' => 'application/xml',
49
+ '.asr' => 'video/x-ms-asf',
50
+ '.asx' => 'video/x-ms-asf',
51
+ '.atom' => 'application/atom+xml',
52
+ '.au' => 'audio/basic',
53
+ '.avi' => 'video/x-msvideo',
54
+ '.axs' => 'application/olescript',
55
+ '.bas' => 'text/plain',
56
+ '.bcpio' => 'application/x-bcpio',
57
+ '.bin' => 'application/octet-stream',
58
+ '.bmp' => 'image/bmp',
59
+ '.c' => 'text/plain',
60
+ '.cab' => 'application/octet-stream',
61
+ '.caf' => 'audio/x-caf',
62
+ '.calx' => 'application/vnd.ms-office.calx',
63
+ '.cat' => 'application/vnd.ms-pki.seccat',
64
+ '.cc' => 'text/plain',
65
+ '.cd' => 'text/plain',
66
+ '.cdda' => 'audio/aiff',
67
+ '.cdf' => 'application/x-cdf',
68
+ '.cer' => 'application/x-x509-ca-cert',
69
+ '.chm' => 'application/octet-stream',
70
+ '.class' => 'application/x-java-applet',
71
+ '.clp' => 'application/x-msclip',
72
+ '.cmx' => 'image/x-cmx',
73
+ '.cnf' => 'text/plain',
74
+ '.cod' => 'image/cis-cod',
75
+ '.config' => 'application/xml',
76
+ '.contact' => 'text/x-ms-contact',
77
+ '.coverage' => 'application/xml',
78
+ '.cpio' => 'application/x-cpio',
79
+ '.cpp' => 'text/plain',
80
+ '.crd' => 'application/x-mscardfile',
81
+ '.crl' => 'application/pkix-crl',
82
+ '.crt' => 'application/x-x509-ca-cert',
83
+ '.cs' => 'text/plain',
84
+ '.csdproj' => 'text/plain',
85
+ '.csh' => 'application/x-csh',
86
+ '.csproj' => 'text/plain',
87
+ '.css' => 'text/css',
88
+ '.csv' => 'text/csv',
89
+ '.cur' => 'application/octet-stream',
90
+ '.cxx' => 'text/plain',
91
+ '.dat' => 'application/octet-stream',
92
+ '.datasource' => 'application/xml',
93
+ '.dbproj' => 'text/plain',
94
+ '.dcr' => 'application/x-director',
95
+ '.def' => 'text/plain',
96
+ '.deploy' => 'application/octet-stream',
97
+ '.der' => 'application/x-x509-ca-cert',
98
+ '.dgml' => 'application/xml',
99
+ '.dib' => 'image/bmp',
100
+ '.dif' => 'video/x-dv',
101
+ '.dir' => 'application/x-director',
102
+ '.disco' => 'text/xml',
103
+ '.dll' => 'application/x-msdownload',
104
+ '.dll.config' => 'text/xml',
105
+ '.dlm' => 'text/dlm',
106
+ '.doc' => 'application/msword',
107
+ '.docm' => 'application/vnd.ms-word.document.macroEnabled.12',
108
+ '.docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
109
+ '.dot' => 'application/msword',
110
+ '.dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
111
+ '.dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
112
+ '.dsp' => 'application/octet-stream',
113
+ '.dsw' => 'text/plain',
114
+ '.dtd' => 'text/xml',
115
+ '.dtsConfig' => 'text/xml',
116
+ '.dv' => 'video/x-dv',
117
+ '.dvi' => 'application/x-dvi',
118
+ '.dwf' => 'drawing/x-dwf',
119
+ '.dwp' => 'application/octet-stream',
120
+ '.dxr' => 'application/x-director',
121
+ '.eml' => 'message/rfc822',
122
+ '.emz' => 'application/octet-stream',
123
+ '.eot' => 'application/octet-stream',
124
+ '.eps' => 'application/postscript',
125
+ '.etl' => 'application/etl',
126
+ '.etx' => 'text/x-setext',
127
+ '.evy' => 'application/envoy',
128
+ '.exe' => 'application/octet-stream',
129
+ '.exe.config' => 'text/xml',
130
+ '.fdf' => 'application/vnd.fdf',
131
+ '.fif' => 'application/fractals',
132
+ '.filters' => 'Application/xml',
133
+ '.fla' => 'application/octet-stream',
134
+ '.flr' => 'x-world/x-vrml',
135
+ '.flv' => 'video/x-flv',
136
+ '.fsscript' => 'application/fsharp-script',
137
+ '.fsx' => 'application/fsharp-script',
138
+ '.generictest' => 'application/xml',
139
+ '.gif' => 'image/gif',
140
+ '.group' => 'text/x-ms-group',
141
+ '.gsm' => 'audio/x-gsm',
142
+ '.gtar' => 'application/x-gtar',
143
+ '.gz' => 'application/x-gzip',
144
+ '.h' => 'text/plain',
145
+ '.hdf' => 'application/x-hdf',
146
+ '.hdml' => 'text/x-hdml',
147
+ '.hhc' => 'application/x-oleobject',
148
+ '.hhk' => 'application/octet-stream',
149
+ '.hhp' => 'application/octet-stream',
150
+ '.hlp' => 'application/winhlp',
151
+ '.hpp' => 'text/plain',
152
+ '.hqx' => 'application/mac-binhex40',
153
+ '.hta' => 'application/hta',
154
+ '.htc' => 'text/x-component',
155
+ '.htm' => 'text/html',
156
+ '.html' => 'text/html',
157
+ '.htt' => 'text/webviewhtml',
158
+ '.hxa' => 'application/xml',
159
+ '.hxc' => 'application/xml',
160
+ '.hxd' => 'application/octet-stream',
161
+ '.hxe' => 'application/xml',
162
+ '.hxf' => 'application/xml',
163
+ '.hxh' => 'application/octet-stream',
164
+ '.hxi' => 'application/octet-stream',
165
+ '.hxk' => 'application/xml',
166
+ '.hxq' => 'application/octet-stream',
167
+ '.hxr' => 'application/octet-stream',
168
+ '.hxs' => 'application/octet-stream',
169
+ '.hxt' => 'text/html',
170
+ '.hxv' => 'application/xml',
171
+ '.hxw' => 'application/octet-stream',
172
+ '.hxx' => 'text/plain',
173
+ '.i' => 'text/plain',
174
+ '.ico' => 'image/x-icon',
175
+ '.ics' => 'application/octet-stream',
176
+ '.idl' => 'text/plain',
177
+ '.ief' => 'image/ief',
178
+ '.iii' => 'application/x-iphone',
179
+ '.inc' => 'text/plain',
180
+ '.inf' => 'application/octet-stream',
181
+ '.inl' => 'text/plain',
182
+ '.ins' => 'application/x-internet-signup',
183
+ '.ipa' => 'application/x-itunes-ipa',
184
+ '.ipg' => 'application/x-itunes-ipg',
185
+ '.ipproj' => 'text/plain',
186
+ '.ipsw' => 'application/x-itunes-ipsw',
187
+ '.iqy' => 'text/x-ms-iqy',
188
+ '.isp' => 'application/x-internet-signup',
189
+ '.ite' => 'application/x-itunes-ite',
190
+ '.itlp' => 'application/x-itunes-itlp',
191
+ '.itms' => 'application/x-itunes-itms',
192
+ '.itpc' => 'application/x-itunes-itpc',
193
+ '.IVF' => 'video/x-ivf',
194
+ '.jar' => 'application/java-archive',
195
+ '.java' => 'application/octet-stream',
196
+ '.jck' => 'application/liquidmotion',
197
+ '.jcz' => 'application/liquidmotion',
198
+ '.jfif' => 'image/pjpeg',
199
+ '.jnlp' => 'application/x-java-jnlp-file',
200
+ '.jpb' => 'application/octet-stream',
201
+ '.jpe' => 'image/jpeg',
202
+ '.jpeg' => 'image/jpeg',
203
+ '.jpg' => 'image/jpeg',
204
+ '.js' => 'application/x-javascript',
205
+ '.jsx' => 'text/jscript',
206
+ '.jsxbin' => 'text/plain',
207
+ '.latex' => 'application/x-latex',
208
+ '.library-ms' => 'application/windows-library+xml',
209
+ '.lit' => 'application/x-ms-reader',
210
+ '.loadtest' => 'application/xml',
211
+ '.lpk' => 'application/octet-stream',
212
+ '.lsf' => 'video/x-la-asf',
213
+ '.lst' => 'text/plain',
214
+ '.lsx' => 'video/x-la-asf',
215
+ '.lzh' => 'application/octet-stream',
216
+ '.m13' => 'application/x-msmediaview',
217
+ '.m14' => 'application/x-msmediaview',
218
+ '.m1v' => 'video/mpeg',
219
+ '.m2t' => 'video/vnd.dlna.mpeg-tts',
220
+ '.m2ts' => 'video/vnd.dlna.mpeg-tts',
221
+ '.m2v' => 'video/mpeg',
222
+ '.m3u' => 'audio/x-mpegurl',
223
+ '.m3u8' => 'audio/x-mpegurl',
224
+ '.m4a' => 'audio/m4a',
225
+ '.m4b' => 'audio/m4b',
226
+ '.m4p' => 'audio/m4p',
227
+ '.m4r' => 'audio/x-m4r',
228
+ '.m4v' => 'video/x-m4v',
229
+ '.mac' => 'image/x-macpaint',
230
+ '.mak' => 'text/plain',
231
+ '.man' => 'application/x-troff-man',
232
+ '.manifest' => 'application/x-ms-manifest',
233
+ '.map' => 'text/plain',
234
+ '.master' => 'application/xml',
235
+ '.mda' => 'application/msaccess',
236
+ '.mdb' => 'application/x-msaccess',
237
+ '.mde' => 'application/msaccess',
238
+ '.mdp' => 'application/octet-stream',
239
+ '.me' => 'application/x-troff-me',
240
+ '.mfp' => 'application/x-shockwave-flash',
241
+ '.mht' => 'message/rfc822',
242
+ '.mhtml' => 'message/rfc822',
243
+ '.mid' => 'audio/mid',
244
+ '.midi' => 'audio/mid',
245
+ '.mix' => 'application/octet-stream',
246
+ '.mk' => 'text/plain',
247
+ '.mmf' => 'application/x-smaf',
248
+ '.mno' => 'text/xml',
249
+ '.mny' => 'application/x-msmoney',
250
+ '.mod' => 'video/mpeg',
251
+ '.mov' => 'video/quicktime',
252
+ '.movie' => 'video/x-sgi-movie',
253
+ '.mp2' => 'video/mpeg',
254
+ '.mp2v' => 'video/mpeg',
255
+ '.mp3' => 'audio/mpeg',
256
+ '.mp4' => 'video/mp4',
257
+ '.mp4v' => 'video/mp4',
258
+ '.mpa' => 'video/mpeg',
259
+ '.mpe' => 'video/mpeg',
260
+ '.mpeg' => 'video/mpeg',
261
+ '.mpf' => 'application/vnd.ms-mediapackage',
262
+ '.mpg' => 'video/mpeg',
263
+ '.mpp' => 'application/vnd.ms-project',
264
+ '.mpv2' => 'video/mpeg',
265
+ '.mqv' => 'video/quicktime',
266
+ '.ms' => 'application/x-troff-ms',
267
+ '.msi' => 'application/octet-stream',
268
+ '.mso' => 'application/octet-stream',
269
+ '.mts' => 'video/vnd.dlna.mpeg-tts',
270
+ '.mtx' => 'application/xml',
271
+ '.mvb' => 'application/x-msmediaview',
272
+ '.mvc' => 'application/x-miva-compiled',
273
+ '.mxp' => 'application/x-mmxp',
274
+ '.nc' => 'application/x-netcdf',
275
+ '.nsc' => 'video/x-ms-asf',
276
+ '.nws' => 'message/rfc822',
277
+ '.ocx' => 'application/octet-stream',
278
+ '.oda' => 'application/oda',
279
+ '.odc' => 'text/x-ms-odc',
280
+ '.odh' => 'text/plain',
281
+ '.odl' => 'text/plain',
282
+ '.odp' => 'application/vnd.oasis.opendocument.presentation',
283
+ '.ods' => 'application/oleobject',
284
+ '.odt' => 'application/vnd.oasis.opendocument.text',
285
+ '.one' => 'application/onenote',
286
+ '.onea' => 'application/onenote',
287
+ '.onepkg' => 'application/onenote',
288
+ '.onetmp' => 'application/onenote',
289
+ '.onetoc' => 'application/onenote',
290
+ '.onetoc2' => 'application/onenote',
291
+ '.orderedtest' => 'application/xml',
292
+ '.osdx' => 'application/opensearchdescription+xml',
293
+ '.p10' => 'application/pkcs10',
294
+ '.p12' => 'application/x-pkcs12',
295
+ '.p7b' => 'application/x-pkcs7-certificates',
296
+ '.p7c' => 'application/pkcs7-mime',
297
+ '.p7m' => 'application/pkcs7-mime',
298
+ '.p7r' => 'application/x-pkcs7-certreqresp',
299
+ '.p7s' => 'application/pkcs7-signature',
300
+ '.pbm' => 'image/x-portable-bitmap',
301
+ '.pcast' => 'application/x-podcast',
302
+ '.pct' => 'image/pict',
303
+ '.pcx' => 'application/octet-stream',
304
+ '.pcz' => 'application/octet-stream',
305
+ '.pdf' => 'application/pdf',
306
+ '.pfb' => 'application/octet-stream',
307
+ '.pfm' => 'application/octet-stream',
308
+ '.pfx' => 'application/x-pkcs12',
309
+ '.pgm' => 'image/x-portable-graymap',
310
+ '.pic' => 'image/pict',
311
+ '.pict' => 'image/pict',
312
+ '.pkgdef' => 'text/plain',
313
+ '.pkgundef' => 'text/plain',
314
+ '.pko' => 'application/vnd.ms-pki.pko',
315
+ '.pls' => 'audio/scpls',
316
+ '.pma' => 'application/x-perfmon',
317
+ '.pmc' => 'application/x-perfmon',
318
+ '.pml' => 'application/x-perfmon',
319
+ '.pmr' => 'application/x-perfmon',
320
+ '.pmw' => 'application/x-perfmon',
321
+ '.png' => 'image/png',
322
+ '.pnm' => 'image/x-portable-anymap',
323
+ '.pnt' => 'image/x-macpaint',
324
+ '.pntg' => 'image/x-macpaint',
325
+ '.pnz' => 'image/png',
326
+ '.pot' => 'application/vnd.ms-powerpoint',
327
+ '.potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
328
+ '.potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
329
+ '.ppa' => 'application/vnd.ms-powerpoint',
330
+ '.ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
331
+ '.ppm' => 'image/x-portable-pixmap',
332
+ '.pps' => 'application/vnd.ms-powerpoint',
333
+ '.ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
334
+ '.ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
335
+ '.ppt' => 'application/vnd.ms-powerpoint',
336
+ '.pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
337
+ '.pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
338
+ '.prf' => 'application/pics-rules',
339
+ '.prm' => 'application/octet-stream',
340
+ '.prx' => 'application/octet-stream',
341
+ '.ps' => 'application/postscript',
342
+ '.psc1' => 'application/PowerShell',
343
+ '.psd' => 'application/octet-stream',
344
+ '.psess' => 'application/xml',
345
+ '.psm' => 'application/octet-stream',
346
+ '.psp' => 'application/octet-stream',
347
+ '.pub' => 'application/x-mspublisher',
348
+ '.pwz' => 'application/vnd.ms-powerpoint',
349
+ '.qht' => 'text/x-html-insertion',
350
+ '.qhtm' => 'text/x-html-insertion',
351
+ '.qt' => 'video/quicktime',
352
+ '.qti' => 'image/x-quicktime',
353
+ '.qtif' => 'image/x-quicktime',
354
+ '.qtl' => 'application/x-quicktimeplayer',
355
+ '.qxd' => 'application/octet-stream',
356
+ '.ra' => 'audio/x-pn-realaudio',
357
+ '.ram' => 'audio/x-pn-realaudio',
358
+ '.rar' => 'application/octet-stream',
359
+ '.ras' => 'image/x-cmu-raster',
360
+ '.rat' => 'application/rat-file',
361
+ '.rc' => 'text/plain',
362
+ '.rc2' => 'text/plain',
363
+ '.rct' => 'text/plain',
364
+ '.rdlc' => 'application/xml',
365
+ '.resx' => 'application/xml',
366
+ '.rf' => 'image/vnd.rn-realflash',
367
+ '.rgb' => 'image/x-rgb',
368
+ '.rgs' => 'text/plain',
369
+ '.rm' => 'application/vnd.rn-realmedia',
370
+ '.rmi' => 'audio/mid',
371
+ '.rmp' => 'application/vnd.rn-rn_music_package',
372
+ '.roff' => 'application/x-troff',
373
+ '.rpm' => 'audio/x-pn-realaudio-plugin',
374
+ '.rqy' => 'text/x-ms-rqy',
375
+ '.rtf' => 'application/rtf',
376
+ '.rtx' => 'text/richtext',
377
+ '.ruleset' => 'application/xml',
378
+ '.s' => 'text/plain',
379
+ '.safariextz' => 'application/x-safari-safariextz',
380
+ '.scd' => 'application/x-msschedule',
381
+ '.sct' => 'text/scriptlet',
382
+ '.sd2' => 'audio/x-sd2',
383
+ '.sdp' => 'application/sdp',
384
+ '.sea' => 'application/octet-stream',
385
+ '.searchConnector-ms' => 'application/windows-search-connector+xml',
386
+ '.setpay' => 'application/set-payment-initiation',
387
+ '.setreg' => 'application/set-registration-initiation',
388
+ '.settings' => 'application/xml',
389
+ '.sgimb' => 'application/x-sgimb',
390
+ '.sgml' => 'text/sgml',
391
+ '.sh' => 'application/x-sh',
392
+ '.shar' => 'application/x-shar',
393
+ '.shtml' => 'text/html',
394
+ '.sit' => 'application/x-stuffit',
395
+ '.sitemap' => 'application/xml',
396
+ '.skin' => 'application/xml',
397
+ '.sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
398
+ '.sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
399
+ '.slk' => 'application/vnd.ms-excel',
400
+ '.sln' => 'text/plain',
401
+ '.slupkg-ms' => 'application/x-ms-license',
402
+ '.smd' => 'audio/x-smd',
403
+ '.smi' => 'application/octet-stream',
404
+ '.smx' => 'audio/x-smd',
405
+ '.smz' => 'audio/x-smd',
406
+ '.snd' => 'audio/basic',
407
+ '.snippet' => 'application/xml',
408
+ '.snp' => 'application/octet-stream',
409
+ '.sol' => 'text/plain',
410
+ '.sor' => 'text/plain',
411
+ '.spc' => 'application/x-pkcs7-certificates',
412
+ '.spl' => 'application/futuresplash',
413
+ '.src' => 'application/x-wais-source',
414
+ '.srf' => 'text/plain',
415
+ '.SSISDeploymentManifest' => 'text/xml',
416
+ '.ssm' => 'application/streamingmedia',
417
+ '.sst' => 'application/vnd.ms-pki.certstore',
418
+ '.stl' => 'application/vnd.ms-pki.stl',
419
+ '.sv4cpio' => 'application/x-sv4cpio',
420
+ '.sv4crc' => 'application/x-sv4crc',
421
+ '.svc' => 'application/xml',
422
+ '.swf' => 'application/x-shockwave-flash',
423
+ '.t' => 'application/x-troff',
424
+ '.tar' => 'application/x-tar',
425
+ '.tcl' => 'application/x-tcl',
426
+ '.testrunconfig' => 'application/xml',
427
+ '.testsettings' => 'application/xml',
428
+ '.tex' => 'application/x-tex',
429
+ '.texi' => 'application/x-texinfo',
430
+ '.texinfo' => 'application/x-texinfo',
431
+ '.tgz' => 'application/x-compressed',
432
+ '.thmx' => 'application/vnd.ms-officetheme',
433
+ '.thn' => 'application/octet-stream',
434
+ '.tif' => 'image/tiff',
435
+ '.tiff' => 'image/tiff',
436
+ '.tlh' => 'text/plain',
437
+ '.tli' => 'text/plain',
438
+ '.toc' => 'application/octet-stream',
439
+ '.tr' => 'application/x-troff',
440
+ '.trm' => 'application/x-msterminal',
441
+ '.trx' => 'application/xml',
442
+ '.ts' => 'video/vnd.dlna.mpeg-tts',
443
+ '.tsv' => 'text/tab-separated-values',
444
+ '.ttf' => 'application/octet-stream',
445
+ '.tts' => 'video/vnd.dlna.mpeg-tts',
446
+ '.txt' => 'text/plain',
447
+ '.u32' => 'application/octet-stream',
448
+ '.uls' => 'text/iuls',
449
+ '.user' => 'text/plain',
450
+ '.ustar' => 'application/x-ustar',
451
+ '.vb' => 'text/plain',
452
+ '.vbdproj' => 'text/plain',
453
+ '.vbk' => 'video/mpeg',
454
+ '.vbproj' => 'text/plain',
455
+ '.vbs' => 'text/vbscript',
456
+ '.vcf' => 'text/x-vcard',
457
+ '.vcproj' => 'Application/xml',
458
+ '.vcs' => 'text/plain',
459
+ '.vcxproj' => 'Application/xml',
460
+ '.vddproj' => 'text/plain',
461
+ '.vdp' => 'text/plain',
462
+ '.vdproj' => 'text/plain',
463
+ '.vdx' => 'application/vnd.ms-visio.viewer',
464
+ '.vml' => 'text/xml',
465
+ '.vscontent' => 'application/xml',
466
+ '.vsct' => 'text/xml',
467
+ '.vsd' => 'application/vnd.visio',
468
+ '.vsi' => 'application/ms-vsi',
469
+ '.vsix' => 'application/vsix',
470
+ '.vsixlangpack' => 'text/xml',
471
+ '.vsixmanifest' => 'text/xml',
472
+ '.vsmdi' => 'application/xml',
473
+ '.vspscc' => 'text/plain',
474
+ '.vss' => 'application/vnd.visio',
475
+ '.vsscc' => 'text/plain',
476
+ '.vssettings' => 'text/xml',
477
+ '.vssscc' => 'text/plain',
478
+ '.vst' => 'application/vnd.visio',
479
+ '.vstemplate' => 'text/xml',
480
+ '.vsto' => 'application/x-ms-vsto',
481
+ '.vsw' => 'application/vnd.visio',
482
+ '.vsx' => 'application/vnd.visio',
483
+ '.vtx' => 'application/vnd.visio',
484
+ '.wav' => 'audio/wav',
485
+ '.wave' => 'audio/wav',
486
+ '.wax' => 'audio/x-ms-wax',
487
+ '.wbk' => 'application/msword',
488
+ '.wbmp' => 'image/vnd.wap.wbmp',
489
+ '.wcm' => 'application/vnd.ms-works',
490
+ '.wdb' => 'application/vnd.ms-works',
491
+ '.wdp' => 'image/vnd.ms-photo',
492
+ '.webarchive' => 'application/x-safari-webarchive',
493
+ '.webtest' => 'application/xml',
494
+ '.wiq' => 'application/xml',
495
+ '.wiz' => 'application/msword',
496
+ '.wks' => 'application/vnd.ms-works',
497
+ '.WLMP' => 'application/wlmoviemaker',
498
+ '.wlpginstall' => 'application/x-wlpg-detect',
499
+ '.wlpginstall3' => 'application/x-wlpg3-detect',
500
+ '.wm' => 'video/x-ms-wm',
501
+ '.wma' => 'audio/x-ms-wma',
502
+ '.wmd' => 'application/x-ms-wmd',
503
+ '.wmf' => 'application/x-msmetafile',
504
+ '.wml' => 'text/vnd.wap.wml',
505
+ '.wmlc' => 'application/vnd.wap.wmlc',
506
+ '.wmls' => 'text/vnd.wap.wmlscript',
507
+ '.wmlsc' => 'application/vnd.wap.wmlscriptc',
508
+ '.wmp' => 'video/x-ms-wmp',
509
+ '.wmv' => 'video/x-ms-wmv',
510
+ '.wmx' => 'video/x-ms-wmx',
511
+ '.wmz' => 'application/x-ms-wmz',
512
+ '.wpl' => 'application/vnd.ms-wpl',
513
+ '.wps' => 'application/vnd.ms-works',
514
+ '.wri' => 'application/x-mswrite',
515
+ '.wrl' => 'x-world/x-vrml',
516
+ '.wrz' => 'x-world/x-vrml',
517
+ '.wsc' => 'text/scriptlet',
518
+ '.wsdl' => 'text/xml',
519
+ '.wvx' => 'video/x-ms-wvx',
520
+ '.x' => 'application/directx',
521
+ '.xaf' => 'x-world/x-vrml',
522
+ '.xaml' => 'application/xaml+xml',
523
+ '.xap' => 'application/x-silverlight-app',
524
+ '.xbap' => 'application/x-ms-xbap',
525
+ '.xbm' => 'image/x-xbitmap',
526
+ '.xdr' => 'text/plain',
527
+ '.xht' => 'application/xhtml+xml',
528
+ '.xhtml' => 'application/xhtml+xml',
529
+ '.xla' => 'application/vnd.ms-excel',
530
+ '.xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
531
+ '.xlc' => 'application/vnd.ms-excel',
532
+ '.xld' => 'application/vnd.ms-excel',
533
+ '.xlk' => 'application/vnd.ms-excel',
534
+ '.xll' => 'application/vnd.ms-excel',
535
+ '.xlm' => 'application/vnd.ms-excel',
536
+ '.xls' => 'application/vnd.ms-excel',
537
+ '.xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
538
+ '.xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
539
+ '.xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
540
+ '.xlt' => 'application/vnd.ms-excel',
541
+ '.xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
542
+ '.xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
543
+ '.xlw' => 'application/vnd.ms-excel',
544
+ '.xml' => 'text/xml',
545
+ '.xmta' => 'application/xml',
546
+ '.xof' => 'x-world/x-vrml',
547
+ '.XOML' => 'text/plain',
548
+ '.xpm' => 'image/x-xpixmap',
549
+ '.xps' => 'application/vnd.ms-xpsdocument',
550
+ '.xrm-ms' => 'text/xml',
551
+ '.xsc' => 'application/xml',
552
+ '.xsd' => 'text/xml',
553
+ '.xsf' => 'text/xml',
554
+ '.xsl' => 'text/xml',
555
+ '.xslt' => 'text/xml',
556
+ '.xsn' => 'application/octet-stream',
557
+ '.xss' => 'application/xml',
558
+ '.xtp' => 'application/octet-stream',
559
+ '.xwd' => 'image/x-xwindowdump',
560
+ '.z' => 'application/x-compress',
561
+ '.zip' => 'application/x-zip-compressed'
562
+ }
563
+ end
564
+ end