I've read something about MIME and finfo() but I didn't understand!
Also I tried these:
if ($_FILES["uploadedFile"]["type"] == "text/docx"/*or == document/docx*/)
echo "1";
It is obviously that it won't work.
When I echo $_FILES['uploadedFile']['type']; then I saw this for a word document(My server is Linux):
application/vnd.openxmlformats-officedocument.wordprocessingml.document
So must I use: ?
if ($_FILES["uploadedFile"]["type"] == "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
What is an easy and reliable way to find file extension(Not only Images)?
(I mean using some variables which are not filled on client side)
If you are using php 5.3, you can get true mime-type:
$finfo = finfo_open();
$file = $_FILES["uploadedFile"];
finfo_file($finfo, $file, FILEINFO_MIME_TYPE);
finfo_close($finfo);
More Info:
http://php.net/manual/en/function.finfo-open.php
How about
$file = $_FILES['uploadedFile'['name'];
$pathparts = pathinfo($file);
$ext = $pathparts['extension'];
This will give you the actual file extension to work with.
The best way to determine the file type is by examining the first few bytes of a file – referred to as “magic bytes”. Magic bytes are essentially signatures that vary in length between 2 to 40 bytes in the file headers, or at the end of a file.
your best bet is PECL extension called Fileinfo.
As of PHP 5.3, Fileinfo is shipped with the main distribution and is enabled by default
// in PHP 4 :
$fhandle = finfo_open(FILEINFO_MIME);
$mime_type = finfo_file($fhandle,$file); // e.g. gives for example "image/jpeg" for a jpeg file
// in PHP 5 you can do :
$file_info = new finfo(FILEINFO_MIME); // object oriented approach!
$mime_type = $file_info->buffer(file_get_contents($file));
Related
Hi I am looking for best way to find out mime type in php for any local file or url.
I have tried mime_content_type function of php but since it is deprecated I am looking for better solution in php for all file format.
mime_content_type — Detect MIME Content-type for a file ***(deprecated)***
I have already tried below function
echo 'welcome';
if (function_exists('finfo_open')) {
echo 'testing';
$finfo = finfo_open(FILEINFO_MIME);
$mimetype = finfo_file($finfo, "http://4images.in/wp-content/uploads/2013/12/Siberian-Tiger-Running-Through-Snow-Tom-Brakefield-Getty-Images-200353826-001.jpg");
finfo_close($finfo);
echo $mimetype;
}
Above code is not working for me, I am only seeing welcome for output.I am not sure if I am doing something wrong here.
Below code works somehow in my local but it does not work for urls.
$file = './apache_pb2.png';
$file_info = new finfo(FILEINFO_MIME); // object oriented approach!
$mime_type = $file_info->buffer(file_get_contents($file)); // e.g. gives "image/jpeg"
$mime = explode(';', $mime_type);
print $mime[0];
Is there some work around which work for both(url and local).what is the best practice to set mime type for all contents (image, video, file etc.) other than mime_content_type function in php.also is it recommended to use the mime_content_type function in php, Is it best practice in php ?
Make use of file_info in PHP with FILEINFO_MIME_TYPE flag as the parameter.
[Example taken as it is from PHP Manual]
<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
foreach (glob("*") as $filename) {
echo finfo_file($finfo, $filename) . "\n";
}
finfo_close($finfo);
?>
OUTPUT :
text/html
image/gif
application/vnd.ms-excel
EDIT :
You need to enable the extension on your PHP.ini
;extension=php_fileinfo.dll
Remove the semicolon from that line and restart your webserver and you are good to go. Installation Doc.
Found the answer,
To find the extension of the file best way is to use path_info for both local files and url.
$info = pathinfo($filename);
$basename = $info['basename'];
$ext = $info['extension'];
create an array for the mime type
$mimeTypes = array("mp4" => "video/mp4");// --> See Example here and Here
//get the mime type for file
$type = isset($this->mime_types[$ext]) ? $this->mime_types[$ext] : "application/octet-stream";
Above code works for both url and local files.
Note :
Those struggling with CDN mp4 video mime type video/mp4 issue - I had
made a change in my class.s3.php file -> in mime_type[] array and also
cross checked with putObject() function.
Setting of mime type is always done in coding side and not in AWS S3
bucket, We need to use AWS PHP Class file or sdk to do the
manipulation in mime type or make the necessary changes in core class
file (eg. class.s3.php )
$type = image_type_to_mime_type(exif_imagetype($file));
After I tried all these solutions above that's what I use:
$command = "file -i {$filename}";
$mimeTypeArr = shell_exec($command);
This command returns the line below:
filename: mime_type
After I have this I explode and get what I need.
$mimeTypeArr = shell_exec($command);
$mimeTypeArr = explode(':', $mimeTypeArr);
$mimeType = trim($mimeTypeArr[1]);
Hope it helps!
I'm on 5.4 and looking to detect a mime type from my file handle. I know I can save off a file and then use functions by passing strings, but we want to avoid using strings. So is there a way without any strings?
Instead of passing a file handle or a string, pass an SplFileObject. Using this, you get OO access to the file without directly calling file system functions. Functions that require a pathname can still by used by calling ->getRealPath() on the object.
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime_type = $finfo->file( $fileObject->getRealPath() );
If your PHP installation supports Fileinfo:
$finfo = new finfo;
$mime = $finfo->file($file, FILEINFO_MIME);
finfo_close($finfo);
Where $file would be the full path to the file. $mime will then contain it's MIME type, for example 'image/jpeg' for a JPG image or 'text/x-php' for a PHP script.
Use fileinfo
$fileinfo = finfo_file($finfo, $file, FILEINFO_MIME);
finfo_close($finfo);
Or, you could do it the object-oriented way:
$finfo = new finfo();
$file = '/path/to/file/';
$fileinfo = $finfo->file($file, FILEINFO_MIME);
Use stream_get_meta_data to extract uri
$mime = mime_content_type(
stream_get_meta_data($fh)['uri']
);
Where $fh is our filehandle
AFAIK there's nothing inside a file content bytes that specifically tell the mime type. You have two options:
Detect the contents inspecting the bytes (actually I don't think this should be considered an option, given the difficulty and the performance implications involved).
Detect the mime type inspecting the file extension (if such extension exists): this method isn't error-proof, but is the accepted way of doing this (IMO). If the file haven't any extension, then you have a problem that can't be easily solved.
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)
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
For upload:
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.
For download:
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).
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
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
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
}
}
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 '.'
I am trying to do a restricted file upload using PHP.
I have used
if (($_FILES["file"]["type"] == "application/dbase")
||($_FILES["file"]["type"] == "application/dbf")
||($_FILES["file"]["type"] == "application/x-dbase")
||($_FILES["file"]["type"] == "application/x-dbf")
||($_FILES["file"]["type"] == "zz-application/zz-winassoc-dbf"))
For me .dbf (i.e Microsoft Visual FoxPro Table type) files are not working. Please suggest to me what I should put for the content type for .dbf .
The browser uploading the file probably doesn't know it's an application/dbf mime-time, and sends it as the generic "application/octet-stream". The client/browser has to set the mime-type to be known on upload, and this can be altered by the user!
Thus MIME-type isn't reliable. If you want to be sure that it's the correct file-type/format, you'll have to examine the uploaded file.
There is another easy way for this problem , instead of inspecting the MIME type,
we can get the file extension of the uploaded file by using this function.
$filename=$_FILES["file"]["tmp_name"];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$ext = strtolower($ext);
if($ext=="png"||$ext=="gif"||$ext=="jpg"||$ext=="jpeg"||$ext=="pdf"
||$ext=="doc"||$ext=="docx"||$ext=="xls"
||$ext=="xlsx"||$ext=="xlsm"||$ext=="dbf")
{
// your code whatever you want to write;
}
Find an easy blob-upload and download of file here Blob-upload
Defining the content type is up to the browser (or other client application), making it easy to tamper with and cannot be relied upon. My guess is that your browser doesn't recognize the .dbf file and defaults to "application/octet-stream".
You can't depend on the type field of a file upload to actually determine its type. First, it can be spoofed by the client. Secondly, the client simply might not know what the file type actually is and just report 'application/octet-stream' instead.
you'll have to determine what kind of file was uploaded yourself. Fortunately, PHP provides the fileinfo extension, which can help you with determining the type of a file.
Code example based on one from php.net:
<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
echo finfo_file($finfo, $_FILES["file"]["tmp_name"]) . "\n";
finfo_close($finfo);
?>
http://www.php.net/manual/en/ref.fileinfo.php
Try inspecting the MIME type being passed to you when you upload a file of that type. Insert a temporary print $_FILES["file"]["type"]; somewhere in your code, then upload the file to run the code and see what it prints out! You can then copy that type and use it in your if-statement.
I have an index.php file which has to process many different file types. How do I guess the filetype based on the REQUEST_URI?
If I request http://site/image.jpg, and all requests redirect through index.php, which looks like this
<?php
include('/www/site'.$_SERVER['REQUEST_URI']);
?>
How would I make that work correctly?
Should I test based on the extension of the file requested, or is there a way to get the filetype?
If you are sure you're only ever working with images, you can check out the exif_imagetype() PHP function, which attempts to return the image MIME type.
If you don't mind external dependencies, you can also check out the excellent getID3 library which can determine the MIME type of many different file types.
Lastly, you can check out the mime_content_type() function - but it has been deprecated for the Fileinfo PECL extension.
mime_content_type() is deprecated, so you won't be able to count on it working in the future. There is a "fileinfo" PECL extension, but I haven't heard good things about it.
If you are running on a Unix-like server, you can do the following, which has worked fine for me:
$file = escapeshellarg($filename);
$mime = shell_exec("file -bi " . $file);
$filename should probably include the absolute path.
function get_mime($file) {
if (function_exists("finfo_file")) {
$finfo = finfo_open(FILEINFO_MIME_TYPE); // Return MIME type a la the 'mimetype' extension
$mime = finfo_file($finfo, $file);
finfo_close($finfo);
return $mime;
} else if (function_exists("mime_content_type")) {
return mime_content_type($file);
} else if (!stristr(ini_get("disable_functions"), "shell_exec")) {
// http://stackoverflow.com/a/134930/1593459
$file = escapeshellarg($file);
$mime = shell_exec("file -bi " . $file);
return $mime;
} else {
return false;
}
}
For me, nothing of this works—mime_content_type is deprecated, finfo is not installed, and shell_exec is not allowed.
I actually got fed up by the lack of standard MIME sniffing methods in PHP. Install fileinfo... Use deprecated functions... Oh, these work, but only for images! I got fed up of it, so I did some research and found the WHATWG MIME sniffing specification - I believe this is still a draft specification though.
Anyway, using this specification, I was able to implement a MIME sniffer in PHP. Performance is not an issue. In fact, on my humble machine, I was able to open and sniff thousands of files before PHP timed out.
Here is the MimeReader class.
require_once("MimeReader.php");
$mime = new MimeReader(<YOUR FILE PATH>);
$mime_type_string = $mime->getType(); // "image/jpeg", etc.
If you are working with images only and you need a MIME type (e.g., for headers), then this is the fastest and most direct answer:
$file = 'path/to/image.jpg';
$image_mime = image_type_to_mime_type(exif_imagetype($file));
It will output true image MIME type even if you rename your image file.
You can use finfo to accomplish this as of PHP 5.3:
<?php
$info = new finfo(FILEINFO_MIME_TYPE);
echo $info->file('myImage.jpg');
// prints "image/jpeg"
The FILEINFO_MIME_TYPE flag is optional; without it you get a more verbose string for some files; (apparently some image types will return size and colour depth information). Using the FILEINFO_MIME flag returns the mime-type and encoding if available (e.g. image/png; charset=binary or text/x-php; charset=us-ascii). See this site for more info.
According to the PHP manual, the finfo-file function is best way to do this. However, you will need to install the FileInfo PECL extension.
If the extension is not an option, you can use the outdated mime_content_type function.
mime_content_type() appears to be the way to go, notwithstanding the previous comments saying it is deprecated. It is not -- or at least this incarnation of mime_content_type() is not deprecated, according to http://php.net/manual/en/function.mime-content-type.php. It is part of the FileInfo extension, but the PHP documentation now tells us it is enabled by default as of PHP 5.3.0.
If you run Linux and have the extension you could simply read the MIME type from /etc/mime.types by making a hash array. You can then store that in memory and simply call the MIME by array key :)
/**
* Helper function to extract all mime types from the default Linux /etc/mime.types
*/
function get_mime_types() {
$mime_types = array();
if (
file_exists('/etc/mime.types') &&
($fh = fopen('/etc/mime.types', 'r')) !== false
) {
while (($line = fgets($fh)) !== false) {
if (!trim($line) || substr($line, 0, 1) === '#') continue;
$mime_type = preg_split('/\t+/', rtrim($line));
if (
is_array($mime_type) &&
isset($mime_type[0]) && $mime_type[0] &&
isset($mime_type[1]) && $mime_type[1]
) {
foreach (explode(' ', $mime_type[1]) as $ext) {
$mime_types[$ext] = $mime_type[0];
}
}
}
fclose($fh);
}
return $mime_types;
}
I haven't used it, but there's a PECL extension for getting a file's MIME type. The official documentation for it is in the manual.
Depending on your purpose, a file extension can be ok, but it's not incredibly reliable since it's so easily changed.
If you're only dealing with images, you can use the [getimagesize()][1] function which contains all sorts of information about the image, including the type.
A more general approach would be to use the FileInfo extension from PECL.
Some people have serious complaints about that extension... so if you run into serious issues or cannot install the extension for some reason you might want to check out the deprecated function mime_content_type().
The MIME type of any file on your server can be gotten with this:
<?php
function get_mime($file_path){
$finfo = new finfo(FILEINFO_MIME_TYPE);
$type = $finfo->file(file_path);
}
$mime = get_mime('path/to/file.ext');
I got very good results using a user function from
http://php.net/manual/de/function.mime-content-type.php
#''john dot howard at prismmg dot com 26-Oct-2009 03:43''
function get_mime_type($filename, $mimePath = '../etc') { ...
which doesn’t use finfo, exec or a deprecated function.
It works well also with remote resources!