Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Getting the mime type of an uploaded file is easy enough:

echo mime_content_type($fileatt['tmp_name']);

However, I also want to check the mime-type of files which are included in a zipped file. After unzipping my files (looping through the files in the zip and where i is the current file), I've tried:

$info = pathinfo($zip->getNameIndex($i));
echo mime_content_type($info['dirname'] . "\\" . $info['basename']);

which gives the error: Warning: mime_content_type() [function.mime-content-type]: File or path not found '.\foo.pdf' in C:\Users\<user>\<website>\validation.php on line 56

I realised that the dirname for a zipped file is relative to the zip file, not the absolute path, so I tried:

$a = pathinfo($fileatt['tmp_name']);
$b = $a['dirname'] . "\\" . $info['basename'];
echo mime_content_type($b);

which gives the error: Warning: mime_content_type() [function.mime-content-type]: File or path not found 'C:\xampp\tmp\foo.pdf' in C:\Users\<user>\<website>\validation.php on line 56

Can anyone cast any light on the path of the file? (I suspect the answer might be the same as the comment on getting image height and width from zipped files, but are there any alternative methods?)

UPDATE

Thanks to Baba, the following does work:

$fp = fopen('zip://C:\Users\<user>\<website>\test.zip#foo.jpg', "r");

(n.b. I can only get this to work when I give the full route of the zip file, not a tmp file as would be the case when a file is uploaded via a form). However, trying to get the mime-type: echo mime_content_type($fp); generates the error:

Warning: mime_content_type() [function.mime-content-type]: stream does not support seeking in C:\Users\<user>\<website>\includes\validation.php on line 70

This happens regardless of the file type (i.e. the problem stated in the only comment on http://php.net/manual/en/ziparchive.getstream.php doesn't seem to affect me).

Incidentally, this is also the same error I get when I try a different method: $fp = $zip->getStream('foo.jpg');

I know that there are several other 'stream not supported' questions on SO, but I couldn't work out how they related to my problem, and I was hoping that since this method has been specifically suggested someone might have a good answer...

(p.s. I'm not using the finfo_* functions as my host currently refuses to install PHP v5.3).

You can only use mime_content_type() on physical files, meaning, you'll have to extract files from your zip into a directory somewhere and then loop through them, not just loop through file list off the zip. – Nadh Apr 28, 2012 at 12:05

A. You can start by trying

 mime_content_type('zip:///path/to/file.zip#'. $chapterZip->getNameIndex ( $i ));

B. What i can only think of now is a replacement for mime_content_type it might not be the best approach but am sure it would surface till i figure out a better solution

$chapterZip = new ZipArchive ();
if ($chapterZip->open ( "stockoverflow.zip" )) {
    for($i = 0; $i < $chapterZip->numFiles; $i ++) {
        var_dump ( mime_content_type_replacement ( $chapterZip->getNameIndex ( $i ) ) );

Replacement Function using file extension and finfo_open ( FILEINFO_MIME )

function mime_content_type_replacement($filename) {
    $mime_types = array (
            'txt' => 'text/plain',
            'htm' => 'text/html',
            'html' => 'text/html',
            'php' => 'text/html',
            'css' => 'text/css',
            'js' => 'application/javascript',
            'json' => 'application/json',
            'xml' => 'application/xml',
            'swf' => 'application/x-shockwave-flash',
            'flv' => 'video/x-flv',
            // images
            'png' => 'image/png',
            'jpe' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'jpg' => 'image/jpeg',
            'gif' => 'image/gif',
            'bmp' => 'image/bmp',
            'ico' => 'image/vnd.microsoft.icon',
            'tiff' => 'image/tiff',
            'tif' => 'image/tiff',
            'svg' => 'image/svg+xml',
            'svgz' => 'image/svg+xml',
            // archives
            'zip' => 'application/zip',
            'rar' => 'application/x-rar-compressed',
            'exe' => 'application/x-msdownload',
            'msi' => 'application/x-msdownload',
            'cab' => 'application/vnd.ms-cab-compressed',
            // audio/video
            'mp3' => 'audio/mpeg',
            'qt' => 'video/quicktime',
            'mov' => 'video/quicktime',
            // adobe
            'pdf' => 'application/pdf',
            'psd' => 'image/vnd.adobe.photoshop',
            'ai' => 'application/postscript',
            'eps' => 'application/postscript',
            'ps' => 'application/postscript',
            // ms office
            'doc' => 'application/msword',
            'rtf' => 'application/rtf',
            'xls' => 'application/vnd.ms-excel',
            'ppt' => 'application/vnd.ms-powerpoint',
            // open office
            'odt' => 'application/vnd.oasis.opendocument.text',
            'ods' => 'application/vnd.oasis.opendocument.spreadsheet' 
    $ext = pathinfo ( $filename, PATHINFO_EXTENSION );
    if (array_key_exists ( $ext, $mime_types )) {
        return $mime_types [$ext];
    } elseif (function_exists ( 'finfo_open' )) {
        $finfo = finfo_open ( FILEINFO_MIME );
        $mimetype = finfo_file ( $finfo, $filename );
        finfo_close ( $finfo );
        return $mimetype;
    } else {
        return 'application/octet-stream';

Fore more mime types

PHP / Mime Types - List of mime types publically available?

http://snipplr.com/view/1937/

Edit 1

Just tested the following and it works

$fp = fopen('zip://C:\stockoverflow.zip#1.MOV.xml',"r");

Edit 2

A. mime_content_type($fp) would not work because mime_content_type only accept string argument see http://php.net/manual/en/function.mime-content-type.php

B. Am not sure why you are still sticking to mime_content_type because it has also been depreciated

This function has been deprecated as the PECL extension Fileinfo provides the same functionality (and more) in a much cleaner way.

C. working on $fileatt['tmp_name'] directly is not ideal .. its a temp file and not to be manipulated .. for you to work on that file you need it to copy it to the server where your PHP would have full permission to access it

D. ZipArchive::getStream would only work on a local copy of the zip file not temporary upload file

Thanks for the suggestion. I'm not sure what's wrong: I've got $fp = fopen('zip:\\\\\\'.$a['dirname'].'\\test.zip#file.pdf', 'r'); (backslashes because of Windows, and they all need to be escaped - I assume this is correct?), $a is the same as defined in my question; but I get the error: Warning: fopen(zip:\\\C:\xampp\tmp\test.zip#file.pdf) [function.fopen]: failed to open stream: Invalid argument in C:\Users\<user>\<website>\includes\validation.php on line 60 – ChrisW Apr 28, 2012 at 19:24 thanks for your helpful comments so far; I've put some more info in my question - if you've got any more suggestions I'll be happy to try them :) – ChrisW Apr 29, 2012 at 22:06 I think the overall answer is that it isn't possible to do what I want without saving the zip 1st anyway. The PECL extensions are only included in PHP 5.3+ (which my host won't install - apparently it breaks too many things...). If the finfo_* methods are depreciated what should I be using instead? – ChrisW Apr 29, 2012 at 23:10

I know you mentioned that you couldn't find an answer for php <5.3, but I was a little stuck on this and just figured it out, hopefully it will be of use to those on the latest version - I couldn't see it written anywhere else.

Quite simply, you can use finfo->buffer on the binary data to extract the MIME type, which is available without extracting the contents to a new file.

$fileToUnzip = 0;
$zip = new ZipArchive;
$zip->open("dir/archive.zip");
$binary = $zip->getFromIndex($fileToUnzip);
$filename = $zip->getNameIndex($fileToUnzip);
$zip->close();
$finfo = new finfo(FILEINFO_MIME_TYPE);
$MIMETypeAndCharset = $finfo->buffer($binary);
// discard charset info
$MIMETypeAndCharsetArray = explode(';', $MIMETypeAndCharset);
$MIMEtype = $MIMETypeAndCharsetArray[0];
// you can change the source of an iframe to this php file in order to view a preview
// If the browser can't handle the file, the user is presented with a download box
header('Content-Type:$MIMEtype');
header('Content-Disposition: inline; filename="July Report.pdf"')
echo $binary;

Using above simple [ you can say bigger one 🤪 ] function, you can extract or get the mime type of a file or you can say content.

But before, for using this function you might have need done some pre-configuration,

Like you have to sure that you turned or configured curl extension, filesystem releted extension and finfo extension in php.ini file.

Here, I am describing the whole process of this function in a short.

  • First, we are storing all the updated mime type as an array from official apache mime type url.
  • You can also get this mime type file in your apache conf directory insted of using url. In this function we are using live url to get all the mime type.

  • But the zeroth process for this function is to validate that apache url is live or not.

  • After validating the url, if the url is validated [ means live ], we store all mimes from that url as an array called $mimes

    If the url isn't live or exist we are manually making an array with some common extension available.

  • Then we validate the content as file.

  • Then we check the PHP pathinfo function to insure that is there any file extension or not. If there, store it.

  • After that we checking the $mimes array with our content extension as $mimes array index.

  • Finally we are returning the index value of $mimes array as content mime type through $content_mime variable.

    That's it.

    * **get_content_mime_type * @param string $content, the content or the file whose mime type you want to know. * @return string function get_content_mime_type($content) $url = 'http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'; $url_live = false; $handle = curl_init($url); curl_setopt_array($handle, array( CURLOPT_FOLLOWLOCATION => true, CURLOPT_NOBODY => true, CURLOPT_HEADER => false, CURLOPT_RETURNTRANSFER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false $response = curl_exec($handle); $httpCode = curl_getinfo($handle, CURLINFO_EFFECTIVE_URL); $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); if ($httpCode == 200) $url_live = true; $url_live = $url_live; curl_close($handle); $mimes = array(); if ($url_live) $mimes_file = file_get_contents($url); preg_match_all('#^([^\s]{2,}?)\s+(.+?)$#ism', $mimes_file, $matches, PREG_SET_ORDER); foreach ($matches as $match) $exts = explode(" ", $match[2]); foreach ($exts as $ext) $mimes[$ext] = $match[1]; $mimes = array( 'txt' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html', 'php' => 'text/html', 'css' => 'text/css', 'js' => 'application/javascript', 'json' => 'application/json', 'xml' => 'application/xml', 'swf' => 'application/x-shockwave-flash', 'flv' => 'video/x-flv', // images 'png' => 'image/png', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'bmp' => 'image/bmp', 'ico' => 'image/vnd.microsoft.icon', 'tiff' => 'image/tiff', 'tif' => 'image/tiff', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', // archives 'zip' => 'application/zip', 'rar' => 'application/x-rar-compressed', 'exe' => 'application/x-msdownload', 'msi' => 'application/x-msdownload', 'cab' => 'application/vnd.ms-cab-compressed', // audio/video 'mp3' => 'audio/mpeg', 'qt' => 'video/quicktime', 'mov' => 'video/quicktime', // adobe 'pdf' => 'application/pdf', 'psd' => 'image/vnd.adobe.photoshop', 'ai' => 'application/postscript', 'eps' => 'application/postscript', 'ps' => 'application/postscript', // ms office 'doc' => 'application/msword', 'rtf' => 'application/rtf', 'xls' => 'application/vnd.ms-excel', 'ppt' => 'application/vnd.ms-powerpoint', 'docx' => 'application/msword', 'xlsx' => 'application/vnd.ms-excel', 'pptx' => 'application/vnd.ms-powerpoint', // open office 'odt' => 'application/vnd.oasis.opendocument.text', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', $content_mime = 'unknown'; if (is_file($content)) if (isset(pathinfo($content) ['extension'])) $content_ext = pathinfo($content) ['extension']; if (isset($mimes[$content_ext])) $content_mime = $mimes[$content_ext]; if (is_readable($content) && is_executable($content)) $finfo = finfo_open(FILEINFO_MIME_TYPE); $content_mime = finfo_file($finfo, $content); if ($content_mime === null | $content_mime === "") $content_mime = "application/octet-stream"; $content_mime = $content_mime; finfo_close($finfo); $content_mime = "application/octet-stream"; // return whatever you want // $content_mime = 'unknown'; $content_mime = $content_mime; return $content_mime;

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.

  •