24

I'm using PHP to send an email with an attachment. The attachment could be any of several different file types (pdf, txt, doc, swf, etc).

First, the script gets the file using "file_get_contents".

Later, the script echoes in the header:

Content-Type: <?php echo $the_content_type; ?>; name="<?php echo $the_file_name; ?>"

How to I set the correct value for $the_content_type?

j0k
  • 22,600
  • 28
  • 79
  • 90
edt
  • 22,010
  • 30
  • 83
  • 118

10 Answers10

29

I am using this function, which includes several fallbacks to compensate for older versions of PHP or simply bad results:

function getFileMimeType($file) {
    if (function_exists('finfo_file')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $type = finfo_file($finfo, $file);
        finfo_close($finfo);
    } else {
        require_once 'upgradephp/ext/mime.php';
        $type = mime_content_type($file);
    }

    if (!$type || in_array($type, array('application/octet-stream', 'text/plain'))) {
        $secondOpinion = exec('file -b --mime-type ' . escapeshellarg($file), $foo, $returnCode);
        if ($returnCode === 0 && $secondOpinion) {
            $type = $secondOpinion;
        }
    }

    if (!$type || in_array($type, array('application/octet-stream', 'text/plain'))) {
        require_once 'upgradephp/ext/mime.php';
        $exifImageType = exif_imagetype($file);
        if ($exifImageType !== false) {
            $type = image_type_to_mime_type($exifImageType);
        }
    }

    return $type;
}

It tries to use the newer PHP finfo functions. If those aren't available, it uses the mime_content_type alternative and includes the drop-in replacement from the Upgrade.php library to make sure this exists. If those didn't return anything useful, it'll try the OS' file command. AFAIK that's only available on *NIX systems, you may want to change that or get rid of it if you plan to use this on Windows. If nothing worked, it tries exif_imagetype as fallback for images only.

I have come to notice that different servers vary widely in their support for the mime type functions, and that the Upgrade.php mime_content_type replacement is far from perfect. The limited exif_imagetype functions, both the original and the Upgrade.php replacement, are working pretty reliably though. If you're only concerned about images, you may only want to use this last one.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • The fallback to the `file` command is redundant. The FileInfo extension (and mime_content_type function) use the same file detection database as the `file` command. – Sander Marechal Jan 18 '11 at 07:31
  • @Sander In my tests I found `mime_content_type` to be somewhat unreliable, or possibly its upgrade.php replacement was, while the `file` call is usually successful. I'll have to look into this more to see when and why it fails under which circumstances. At least it does no harm being there. :) – deceze Jan 18 '11 at 07:38
  • I had a quick look at the Upgrade.php code for mime_content_type. First it tries the FileInfo PECL extension. If that doesn't exist, it tries to parse the `magic` file by itself, in PHP. Problem: It only looks in a few predefined places for the `magic` file. It fails on my Debian Squeeze for example. It's also possible that the parser has bugs, but I didn't check that thoroughly. – Sander Marechal Jan 18 '11 at 08:30
  • @Sander Yeah, I'm not entirely convinced of the quality of the upgrade.php library. As such, since even `mime_content_type` doesn't seem to be available everywhere, I think the fallback to `file` is appropriate. :) – deceze Jan 18 '11 at 08:35
  • Yes. You're probably better off with just FileInfo and a fallback to `file`. – Sander Marechal Jan 18 '11 at 09:46
  • When only detecting image type, I think using `exif_imagetype` by itself is the best approach. I tried using `finfo_file` and it worked *most* of the time, but sometimes it returned the type as being `application/octet-stream` instead of the correct file type. – Nate Aug 02 '14 at 02:01
12

It very easy to have it in php.

Simply call the following php function mime_content_type

<?php
    $filelink= 'uploads/some_file.pdf';
    $the_content_type = "";

    // check if the file exist before
    if(is_file($file_link)) {
        $the_content_type = mime_content_type($file_link);
    }
    // You can now use it here.

?>

PHP documentation of the function mime_content_type() Hope it helps someone

BoCyrill
  • 1,219
  • 16
  • 17
7

With finfo_file: http://us2.php.net/manual/en/function.finfo-file.php

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
4

Here's an example using finfo_open which is available in PHP5 and PECL:

$mimepath='/usr/share/magic'; // may differ depending on your machine
// try /usr/share/file/magic if it doesn't work
$mime = finfo_open(FILEINFO_MIME,$mimepath);
if ($mime===FALSE) {
 throw new Exception('Unable to open finfo');
}
$filetype = finfo_file($mime,$tmpFileName);
finfo_close($mime);
if ($filetype===FALSE) {
 throw new Exception('Unable to recognise filetype');
}

Alternatively, you can use the deprecated mime_ content_ type function:

$filetype=mime_content_type($tmpFileName);

or use the OS's in built functions:

ob_start();
system('/usr/bin/file -i -b ' . realpath($tmpFileName));
$type = ob_get_clean();
$parts = explode(';', $type);
$filetype=trim($parts[0]);
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Richy B.
  • 1,619
  • 12
  • 20
3
function getMimeType( $filename ) {
        $realpath = realpath( $filename );
        if ( $realpath
                && function_exists( 'finfo_file' )
                && function_exists( 'finfo_open' )
                && defined( 'FILEINFO_MIME_TYPE' )
        ) {
                // Use the Fileinfo PECL extension (PHP 5.3+)
                return finfo_file( finfo_open( FILEINFO_MIME_TYPE ), $realpath );
        }
        if ( function_exists( 'mime_content_type' ) ) {
                // Deprecated in PHP 5.3
                return mime_content_type( $realpath );
        }
        return false;
}

This worked for me

Why is mime_content_type() deprecated in PHP?

Community
  • 1
  • 1
George
  • 43
  • 4
1

I guess that i found a short way. Get the image size using:

$infFil=getimagesize($the_file_name);

and

Content-Type: <?php echo $infFil["mime"] ?>; name="<?php echo $the_file_name; ?>"

The getimagesize returns an associative array which have a MIME key

I used it and it works

0

I've tried most of the suggestions, but they all fail for me (I'm inbetween any usefull version of PHP apparantly. I ended up with the following function:

function getShellFileMimetype($file) {
    $type = shell_exec('file -i -b '. escapeshellcmd( realpath($_SERVER['DOCUMENT_ROOT'].$file)) );
    if( strpos($type, ";")!==false ){
        $type = current(explode(";", $type));
    }
    return $type;
}
Martijn
  • 15,791
  • 4
  • 36
  • 68
0
  • From string: $mediaType = (new \finfo(FILEINFO_MIME))->buffer($string)
  • From filename: $mediaType = (new \finfo(FILEINFO_MIME))->file($filename)

The ext-fileinfo module is required (usually it is preinstalled) for PHP.

FILEINFO_MIME - Return the mime type and mime encoding as defined by RFC 2045..

If you use composer, don't forget. to add the ext-fileinfo entry to composer.json

Documentation: https://www.php.net/manual/en/ref.fileinfo.php

Maxim Mandrik
  • 377
  • 1
  • 5
  • 11
-3

I really recommend using a Framework like "CodeIgniter" for seinding Emails. Here is a Screencast about "Sending Emails with CodeIgniter" in only 18 Minutes.

http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-3/

-3

try this:

function ftype($f) {
                    curl_setopt_array(($c = @curl_init((!preg_match("/[a-z]+:\/{2}(?:www\.)?/i",$f) ? sprintf("%s://%s/%s", "http" , $_SERVER['HTTP_HOST'],$f) :  $f))), array(CURLOPT_RETURNTRANSFER => 1, CURLOPT_HEADER => 1));
                        return(preg_match("/Type:\s*(?<mime_type>[^\n]+)/i", @curl_exec($c), $m) && curl_getinfo($c, CURLINFO_HTTP_CODE) != 404)  ? ($m["mime_type"]) : 0;

         }
echo ftype("http://img2.orkut.com/images/medium/1283204135/604747203/ln.jpg"); // print image/jpeg
Jet
  • 1,283
  • 10
  • 7