Wordpress - SVG files not uploading since most recent WP update
In WordPress 4.7.1 a change was introduced that checks for the real mime type of an uploaded file. This breaks uploading file types like SVG or DOCX. There already exist tickets for this issue in WordPress Core, where you can read more about this:
- Some Non-image files fail to upload after 4.7.1 (https://core.trac.wordpress.org/ticket/39550)
- SVG upload support broken in 4.7.1 (https://core.trac.wordpress.org/ticket/39552)
A temporary and recommended workaround (for the time until this issue is fixed) is the following plugin:
Disable Real MIME Check
If you don’t want to use that plugin, here’s the same functionality:
add_filter( 'wp_check_filetype_and_ext', function($data, $file, $filename, $mimes) {
global $wp_version;
if ( '4.7.2' !== $wp_version ) {
return $data;
}
$filetype = wp_check_filetype( $filename, $mimes );
return [
'ext' => $filetype['ext'],
'type' => $filetype['type'],
'proper_filename' => $data['proper_filename']
];
}, 10, 4 );
Notice that this snipped has a version check included to disable the fix as soon as WordPress is updated.
Edit
The issue was initially set to be fixed in 4.7.2. But since 4.7.2 was an urgent security release, the fix didn’t make it into that version. It’s now supposed to be fixed in 4.7.3.
Seems like this might be related to this ticket https://core.trac.wordpress.org/ticket/39552, looks like something that got broken in 4.7.1
Nobody seems to have just worked with what is and that's too bad so here's how I handled...
History / Background
I created a SVG uploader in 2015 based upon a CSS-Tricks article looking at what was. I Also got grid working for image preview, and used a few other fixes. Simple plugin (IMO file-type plugins should be simple)
Solution
There were a few changes for 4.7. The real PITA was that for image/
mime types WP is now using GD on the images. To bypass this I set the svg
extension to use application/svg+xml
so GD wouldn't mess with the file.
Update: as of 4.7.2 some bright spark broke that too in some cases
Then later via hook we hotwire it back to image/svg+xml
. It is the same used in other answers, but we firstly lock it down to our specific case to eliminate effects (is it an SVG file); we can rely on reading $data['ext']
(should be cheaper than the function to get file info as only one comparison and one array / hash access).
Update: as of 4.7.2 $data['ext']
is not always set, so we now if it's length is < 1 extract (potentially unsafe) extension from the filename using
strtolower(end(explode('.', $filename)))
. The reason I'm really fighting using FileInfo is that essentially relying on a PHP extension is too opaque and won't always work for everyone (especially not those compiling without or without access to enable extensions if it's not there). I'd like something that works in-lieu of an extension. It's no longer a matter of having the correct information so for those trusting the output of FileInfo
and having the extension (I believe it's default in 5.6+) it should work. Also because this is a plugin, it's not modifying core you can turn off this code or unregister the hook.
https://github.com/Lewiscowles1986/WordPressSVGPlugin
See
- https://github.com/Lewiscowles1986/WordPressSVGPlugin/blob/master/wp-content/plugins/lc-wp-svg/index.php#L38
- https://github.com/Lewiscowles1986/WordPressSVGPlugin/blob/master/wp-content/plugins/lc-wp-svg/index.php#L74
- https://github.com/Lewiscowles1986/WordPressSVGPlugin/blob/master/wp-content/plugins/lc-wp-svg/index.php#L23
- https://github.com/Lewiscowles1986/WordPressSVGPlugin/blob/master/wp-content/plugins/lc-wp-svg/index.php#L79
Other workarounds
Allowing unfiltered uploads is a horrible solution because as others have said linking to this thread people could upload php files via media uploader (that's bad and if you do it, you should stop and think!)
Forcing every file through any function without checks (Ironically if you have image/
in the mime type you can't just have a simple ext check). This has the potential to create far wider reaching effects to solve a relatively niche problem and introduces more work overall (caveat my plugin also introduces more work for admin users to get admin media UI to work)
If we left the mime as application/svg+xml and simply filtered the mime types the image would upload but would AFAIK require fixes to be used as a featured image etc. There is more work to be done on ensuring universal SVG experience so I chose to pick battles carefully.
Hope this helps.