Reputation: 7338
I'm developing a simple php upload script, and users can upload only ZIP and RAR files.
What MIME types I should use to check $_FILES[x][type]
? (a complete list please)
Upvotes: 190
Views: 341775
Reputation: 44364
An official list of mime types can be found at The Internet Assigned Numbers Authority (IANA) . According to their list Content-Type
header for zip
is application/zip
.
The media type for rar
files, registered at IANA in 2016, is application/vnd.rar
(see https://www.iana.org/assignments/media-types/application/vnd.rar). The mime-type value, application/x-rar-compressed
, was used before that and is still commonly used even though it is marked as deprecated in the document above.
application/octet-stream
means as much as: "I send you a file stream and the content of this stream is not specified" (so it is true that it can be a zip
or rar
file as well). The server is supposed to detect what the actual content of the stream is.
Note: For upload it is not safe to rely on the mime type set in the Content-Type
header. The header is set on the client and can be set to any random value. Instead you can use the php file info functions to detect the file mime-type on the server.
If you want to download a zip
file and nothing else you should only set one single Accept
header value. Any additional values set will be used as a fallback in case the server cannot satisfy your in the Accept
header requested mime-type.
According to the WC3 specifications this:
application/zip, application/octet-stream
will be intrepreted as: "I prefer a application/zip
mime-type, but if you cannot deliver this an application/octet-stream
(a file stream) is also fine".
So only a single:
application/zip
Will guarantee you a zip
file (or a 406 - Not Acceptable
response in case the server is unable to satisfy your request).
Upvotes: 49
Reputation: 8329
The answers from freedompeace, Kiyarash and Sam Vloeberghs:
.rar application/vnd.rar, application/x-rar-compressed, application/octet-stream
.zip application/zip, application/octet-stream, application/x-zip-compressed, multipart/x-zip
I would do a check on the file name too. Here is how you could check if the file is a RAR or ZIP file. I tested it by creating a quick command line application.
<?php
if (isRarOrZip($argv[1])) {
echo 'It is probably a RAR or ZIP file.';
} else {
echo 'It is probably not a RAR or ZIP file.';
}
function isRarOrZip($file) {
// get the first 7 bytes
$bytes = file_get_contents($file, FALSE, NULL, 0, 7);
$ext = strtolower(substr($file, - 4));
// RAR magic number: Rar!\x1A\x07\x00
// http://en.wikipedia.org/wiki/RAR
if ($ext == '.rar' and bin2hex($bytes) == '526172211a0700') {
return TRUE;
}
// ZIP magic number: none, though PK\003\004, PK\005\006 (empty archive),
// or PK\007\008 (spanned archive) are common.
// http://en.wikipedia.org/wiki/ZIP_(file_format)
if ($ext == '.zip' and substr($bytes, 0, 2) == 'PK') {
return TRUE;
}
return FALSE;
}
Notice that it still won't be 100% certain, but it is probably good enough.
$ rar.exe l somefile.zip
somefile.zip is not RAR archive
But even WinRAR detects non RAR files as SFX archives:
$ rar.exe l somefile.srr
SFX Volume somefile.srr
Upvotes: 316
Reputation: 17713
I see many answer reporting for zip and rar the Media Types application/zip
and application/x-rar-compressed
, respectively.
While the former matching is correct, for the latter IANA reports here https://www.iana.org/assignments/media-types/application/vnd.rar that for rar application/x-rar-compressed
is a deprecated alias name and instead application/vnd.rar
is the official one.
So, right Media Types from IANA in 2020 are:
zip
: application/zip
rar
: application/vnd.rar
Upvotes: 4
Reputation: 11834
In a linked question, there's some Objective-C code to get the mime type for a file URL. I've created a Swift extension based on that Objective-C code to get the mime type:
import Foundation
import MobileCoreServices
extension URL {
var mimeType: String? {
guard self.pathExtension.count != 0 else {
return nil
}
let pathExtension = self.pathExtension as CFString
if let preferredIdentifier = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, nil) {
guard let mimeType = UTTypeCopyPreferredTagWithClass(preferredIdentifier.takeRetainedValue(), kUTTagClassMIMEType) else {
return nil
}
return mimeType.takeRetainedValue() as String
}
return nil
}
}
Upvotes: 0
Reputation: 1024
You should not trust $_FILES['upfile']['mime']
, check MIME type by yourself. For that purpose, you may use fileinfo
extension, enabled by default as of PHP 5.3.0.
$fileInfo = new finfo(FILEINFO_MIME_TYPE);
$fileMime = $fileInfo->file($_FILES['upfile']['tmp_name']);
$validMimes = array(
'zip' => 'application/zip',
'rar' => 'application/x-rar',
);
$fileExt = array_search($fileMime, $validMimes, true);
if($fileExt != 'zip' && $fileExt != 'rar')
throw new RuntimeException('Invalid file format.');
NOTE: Don't forget to enable the extension in your php.ini
and restart your server:
extension=php_fileinfo.dll
Upvotes: 7
Reputation: 2823
As extension might contain more or less that three characters the following will test for an extension regardless of the length of it.
Try this:
$allowedExtensions = array( 'mkv', 'mp3', 'flac' );
$temp = explode(".", $_FILES[$file]["name"]);
$extension = strtolower(end($temp));
if( in_array( $extension, $allowedExtensions ) ) { ///
to check for all characters after the last '.'
Upvotes: -3