diff --git a/formats/format_pcm.c b/formats/format_pcm.c
index 4e846d7cfeeb8b380a64cec768dfd31d94c52c2f..674c8b59ad1fb0ac93339b0e6f4efcaf27dd36b4 100644
--- a/formats/format_pcm.c
+++ b/formats/format_pcm.c
@@ -507,6 +507,7 @@ static struct ast_format_def alaw_f = {
 static struct ast_format_def pcm_f = {
 	.name = "pcm",
 	.exts = "pcm|ulaw|ul|mu|ulw",
+	.mime_types = "audio/basic",
 	.write = pcm_write,
 	.seek = pcm_seek,
 	.trunc = pcm_trunc,
diff --git a/formats/format_vox.c b/formats/format_vox.c
index b63e225be918b65110a72bfd81bfc7acbd93bb80..023c40967802cb61d1c57deb65a47c4e5ef087ef 100644
--- a/formats/format_vox.c
+++ b/formats/format_vox.c
@@ -128,6 +128,7 @@ static off_t vox_tell(struct ast_filestream *fs)
 static struct ast_format_def vox_f = {
 	.name = "vox",
 	.exts = "vox",
+	.mime_types = "audio/x-vox",
 	.write = vox_write,
 	.seek = vox_seek,
 	.trunc = vox_trunc,
diff --git a/formats/format_wav.c b/formats/format_wav.c
index 81a686e361f5d26c953a3fc8be016438adb4d44c..ec7e3d37995cfcd27a201456064d3dfd9bff6793 100644
--- a/formats/format_wav.c
+++ b/formats/format_wav.c
@@ -532,6 +532,7 @@ static struct ast_format_def wav16_f = {
 static struct ast_format_def wav_f = {
 	.name = "wav",
 	.exts = "wav",
+	.mime_types = "audio/wav|audio/x-wav",
 	.open =	wav_open,
 	.rewrite = wav_rewrite,
 	.write = wav_write,
diff --git a/include/asterisk/file.h b/include/asterisk/file.h
index c17cb327b3a6468848f96daa40184a010a2e7983..1c2c7a84a0c2fc4a5759b659b4bcee69aee7d48d 100644
--- a/include/asterisk/file.h
+++ b/include/asterisk/file.h
@@ -427,6 +427,18 @@ char *ast_format_str_reduce(char *fmts);
  */
 struct ast_format *ast_get_format_for_file_ext(const char *file_ext);
 
+/*!
+ * \brief Get a suitable filename extension for the given MIME type
+ *
+ * \param mime_type The MIME type for which to find extensions
+ * \param buffer A pointer to a buffer to receive the extension
+ * \param capacity The size of 'buffer' in bytes
+ *
+ * \retval 1 if an extension was found for the provided MIME type
+ * \retval 0 if the MIME type was not found
+ */
+int ast_get_extension_for_mime_type(const char *mime_type, char *buffer, size_t capacity);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
diff --git a/include/asterisk/mod_format.h b/include/asterisk/mod_format.h
index 5f93ea442df8b672835b38cc4ad1c8cca13c4152..6e772f05b296e80e63c8ed4c04edd0fb81041855 100644
--- a/include/asterisk/mod_format.h
+++ b/include/asterisk/mod_format.h
@@ -44,6 +44,7 @@ struct ast_format_def {
 	char name[80];		/*!< Name of format */
 	char exts[80];		/*!< Extensions (separated by | if more than one)
 						 * this format can read.  First is assumed for writing (e.g. .mp3) */
+	char mime_types[80]; /*!< MIME Types related to the format (separated by | if more than one)*/
 	struct ast_format *format;	/*!< Format of frames it uses/provides (one only) */
 	/*!
 	 * \brief Prepare an input stream for playback.
diff --git a/main/file.c b/main/file.c
index 8dded812382054f29344267bf4a2753d5ae79da7..3ee58b1684d66b23cbc3a541ad5eb64f8236e5d0 100644
--- a/main/file.c
+++ b/main/file.c
@@ -333,20 +333,21 @@ static char *build_filename(const char *filename, const char *ext)
 
 /* compare type against the list 'exts' */
 /* XXX need a better algorithm */
-static int exts_compare(const char *exts, const char *type)
+static int type_in_list(const char *list, const char *type, int (*cmp)(const char *s1, const char *s2))
 {
-	char tmp[256];
-	char *stringp = tmp, *ext;
+	char *stringp = ast_strdupa(list), *item;
 
-	ast_copy_string(tmp, exts, sizeof(tmp));
-	while ((ext = strsep(&stringp, "|"))) {
-		if (!strcmp(ext, type))
+	while ((item = strsep(&stringp, "|"))) {
+		if (!cmp(item, type)) {
 			return 1;
+		}
 	}
 
 	return 0;
 }
 
+#define exts_compare(list, type) (type_in_list((list), (type), strcmp))
+
 /*!
  * \internal
  * \brief Close the file stream by canceling any pending read / write callbacks
@@ -1926,6 +1927,27 @@ struct ast_format *ast_get_format_for_file_ext(const char *file_ext)
 	return NULL;
 }
 
+int ast_get_extension_for_mime_type(const char *mime_type, char *buffer, size_t capacity)
+{
+	struct ast_format_def *f;
+	SCOPED_RDLOCK(lock, &formats.lock);
+
+	ast_assert(buffer && capacity);
+
+	AST_RWLIST_TRAVERSE(&formats, f, list) {
+		if (type_in_list(f->mime_types, mime_type, strcasecmp)) {
+			size_t item_len = strcspn(f->exts, "|");
+			size_t bytes_written = snprintf(buffer, capacity, ".%.*s", (int) item_len, f->exts);
+			if (bytes_written < capacity) {
+				/* Only return success if we didn't truncate */
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static struct ast_cli_entry cli_file[] = {
 	AST_CLI_DEFINE(handle_cli_core_show_file_formats, "Displays file formats")
 };
diff --git a/main/media_cache.c b/main/media_cache.c
index e93d1a02fbe3e07d16851b7ee236c1151efe2a73..e0a6dbb7489587a78311060db2b66a703931b08a 100644
--- a/main/media_cache.c
+++ b/main/media_cache.c
@@ -35,6 +35,7 @@
 #include "asterisk/bucket.h"
 #include "asterisk/astdb.h"
 #include "asterisk/cli.h"
+#include "asterisk/file.h"
 #include "asterisk/media_cache.h"
 
 /*! The name of the AstDB family holding items in the cache. */
@@ -123,6 +124,24 @@ static void media_cache_item_del_from_astdb(struct ast_bucket_file *bucket_file)
 	ast_free(hash_value);
 }
 
+/*!
+ * \internal
+ * \brief Normalize the value of a Content-Type header
+ *
+ * This will trim off any optional parameters after the type/subtype.
+ */
+static void normalize_content_type_header(char *content_type)
+{
+	char *params = strchr(content_type, ';');
+
+	if (params) {
+		*params-- = 0;
+		while (params > content_type && (*params == ' ' || *params == '\t')) {
+			*params-- = 0;
+		}
+	}
+}
+
 /*!
  * \internal
  * \brief Update the name of the file backing a \c bucket_file
@@ -142,9 +161,32 @@ static void bucket_file_update_path(struct ast_bucket_file *bucket_file,
 	} else if (!strchr(bucket_file->path, '.') && (ext = strrchr(ast_sorcery_object_get_id(bucket_file), '.'))) {
 		/* If we don't have a file extension and were provided one in the URI, use it */
 		char new_path[PATH_MAX];
+		char found_ext[PATH_MAX];
 
 		ast_bucket_file_metadata_set(bucket_file, "ext", ext);
 
+		/* Don't pass '.' while checking for supported extension */
+		if (!ast_get_format_for_file_ext(ext + 1)) {
+			/* If the file extension passed in the URI isn't supported check for the
+			 * extension based on the MIME type passed in the Content-Type header before
+			 * giving up.
+			 * If a match is found then retrieve the extension from the supported list
+			 * corresponding to the mime-type and use that to rename the file */
+			struct ast_bucket_metadata *header = ast_bucket_file_metadata_get(bucket_file, "content-type");
+			if (header) {
+				char *mime_type = ast_strdup(header->value);
+				if (mime_type) {
+					normalize_content_type_header(mime_type);
+					if (!ast_strlen_zero(mime_type)) {
+						if (ast_get_extension_for_mime_type(mime_type, found_ext, sizeof(found_ext))) {
+							ext = found_ext;
+						}
+					}
+					ast_free(mime_type);
+				}
+			}
+		}
+
 		snprintf(new_path, sizeof(new_path), "%s%s", bucket_file->path, ext);
 		rename(bucket_file->path, new_path);
 		ast_copy_string(bucket_file->path, new_path, sizeof(bucket_file->path));
diff --git a/res/res_http_media_cache.c b/res/res_http_media_cache.c
index eba7ecc618299899360a3a10d9fe004a1c294ace..bca576372c3f6b241f341a387075c0b9183127bd 100644
--- a/res/res_http_media_cache.c
+++ b/res/res_http_media_cache.c
@@ -84,6 +84,7 @@ static size_t curl_header_callback(char *buffer, size_t size, size_t nitems, voi
 	if (strcasecmp(header, "ETag")
 		&& strcasecmp(header, "Cache-Control")
 		&& strcasecmp(header, "Last-Modified")
+		&& strcasecmp(header, "Content-Type")
 		&& strcasecmp(header, "Expires")) {
 		return realsize;
 	}