I'm having no luck getting the MIME type of an uploaded image before that image is saved into a database. I've read books and dozens of web pages but cannot find an answer.
How can I determine the MIME type?
Here's the code I currently have. I've removed the various attempts at determining the MIME type:
$upload_dir = HOST_WWW_ROOT . "uploads/movie_pics/";
$image_fieldname = "movie_pic";
// Name the file uniquely
$now = time();
while (file_exists($upload_filename = $upload_dir . $now .
'-' .
$_FILES[$image_fieldname]['name'])) {
$now++;
}
// Insert the image into the movies_images table
$image = $_FILES[$image_fieldname];
$movie_images_filename = $image['name'];
$movie_images_info = getimagesize($image['tmp_name']);
$finfo = finfo_open();
$movie_images_mime_type = finfo_file($finfo, $upload_filename, FILEINFO_MIME);
finfo_close($finfo);
$movie_images_size = $image['size'];
$movie_images_data = file_get_contents($image['tmp_name']);
$insert_image_sql = sprintf("INSERT INTO movies_images " .
"(movie_images_filename, movie_images_mime_type, movie_images_file_size, movie_images_data) " .
"VALUES ('%s', '%s', %d, '%s');",
mysql_real_escape_string($movie_images_filename),
mysql_real_escape_string($movie_images_mime_type),
mysql_real_escape_string($movie_images_size),
mysql_real_escape_string($movie_images_data));
mysql_query($insert_image_sql)
or die(mysql_error());
From the manual page of finfo_file the example passes the const FILEINFO_MIME_TYPE to finfo_open, rather than finfo_file.
$finfo = finfo_open(FILEINFO_MIME);
$movie_images_mime_type = finfo_file($finfo, $upload_filename);
If you are sure you will only ever be dealing with images you can use the exif_imagetype().
The below code will compare a file to a particular IMAGE type. It then uses image_type_to_mime_type() to retrieve the file's mime-type using the image type stored in $image_type.
Example 1 (extracted from link above)
// if file is a GIF line below should return IMAGETYPE_GIF
$image_type = exif_imagetype('image.gif');
if ($image_type == IMAGETYPE_GIF) {
$mime = image_type_to_mime_type(); // will produce "image/gif" as String.
echo 'The picture is a gif, with a mime type of ' . $mime;
}
Do NOT use mysql_* for new code.
Also, it is advised to no longer use mysql_* functions for new code, as it has been deprecated. I would recommend looking into mysqli_* or PDO forms of MySQL querying.
Related
I'm trying to get mime type of the profile picture they're in format user_id.jpg or gif or png, I experimented with this code but it's not working.
function detectFileMimeType($filename='')
{
$filename = escapeshellcmd($filename);
$command = "file -b --mime-type -m /usr/share/misc/magic {$filename}";
$mimeType = shell_exec($command);
return trim($mimeType);
}
function get_avatar($image, $user_id, $account)
{
$imgurl ="http://mypage/files/pictures/picture-" . ($user_id, $mimeType) . ".jpg";
if (!is_imgurl_good($imgurl)) {
$imgurl = "http://mypage/sites/all/themes/simple_custom/user.png";
}
return $imgurl;
}
You should be able to get the MIME type of a file fairly easily with built in functions provided by PHP -
function detectFileMimeType($filename='')
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type
$fileglob = glob($filename);
echo finfo_file($finfo, $fileglob);
finfo_close($finfo);
}
http://php.net/manual/en/function.finfo-file.php
http://php.net/manual/en/function.glob.php
As well as finfo which works fine, a slightly easier method is to get PHP getimagesize function return, as this will return the MIME type as extracted from the file:
$file = "blah/blahblah/bubbles.jpg";
$fileTypeData = getimagesize($file);
$fileTypeData['mime'] = The Mime type of the image file.
Here is the file upload code. It works in such a way that it accepts all the image extensions. But it needs to validate the file type (video, word doc etc). I need it to only upload images. For an example what happens now is that when I select a word document and submit my form, it shows a bunch of errors, inserts the record but not the file. What should happen is that, if the file is anything other than an image, it should not let the user insert the record. Should get an error message saying to check the file type when the form is submitted. Please assist me in achieving this.
if( isset($_FILES['img']) )
{
//resizing the image
$image = new SimpleImage();
$image->load($_FILES['img']['tmp_name']);
$image->resizeToHeight(180);
$info = pathinfo($_FILES['img']['name']);
$file = 'uploads/' . basename($_FILES['img']['name'],'.'.$info['extension']) . '.png';
if ($image->save($file))
{
if($fp = fopen($file , 'rb'))
{
$data = fread($fp, filesize($file));
//encoding the the image only to text so can be stored in DB
$data = base64_encode($data);
fclose($fp);
}
}
else
{
$error = '<p id="failed">Invalid Image</p>';
}
You need to check MIME type on the image, something like that:
if (isset($_FILES['img'])) {
$file = $_FILES['img'];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
if (strpos($mime, 'image') === false) {
die('The submitted file is not an image!');
}
// Uploading code..
}
If mime string has 'image' in it, then it's image. Hope that will help.
In older PHP versions you can use mime_content_type. However if you have PHP > 5.3 you should use the finfo_* functions
You should also check is_uploaded_file() rather than isset()
if( is_uploaded_file( $_FILES['img']['tmp_name'] ) ) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$type = finfo_file( $_FILES['img']['tmp_name'] );
if( $type == 'image/gif' ) { // for example
// do stuff
}
}
Im about to start on a PHP script to import csv database.
The csv has a column with urls to product images.
What I need to be able to do is get the image, check what type of file it is (jpg, png etc), change the name, save the file to a folder on the server and then insert the file name into the database.
The inserting into the database bit I can do, its the renaming of the file im confused with.
Is it possible to grab the info like you would when uploading a file, for example:
Uploading a file using a file input in a html form
$_FILES['file']['name'];
or
$_FILES['file']['type'];
If downloading a file, could this be possible
$downloaded_image['name'];
or
$downloaded_image['type'];
or is that totally off the mark?
I have never done this before, and most of the answers on stackoverflow don't quite answer my question so was hoping someone could point me in the right direction on how to do this.
EDITED/UPDATED:
Would something like this work to get the file attributes...
$image_id = '123456';
$the_image = file_get_contents($downloaded_image);
$image_name = $the_image['name'];
$image_type = $the_image['type'];
$new_name = $image_id . '.' . $image_type;
$img_path = '/images/';
$save_image = file_put_contents($img_path, $new_name);
if($save_image) {
echo 'image saved';
} else {
echo 'Not Saved';
}
Hopefully im making some sense.
UPDATE: here is the script as it is (still needs tidying up)
define('CSV_PATH','E:/xampp/htdocs/aff/csv-import/');
// path where your CSV file is located
$csv_file = CSV_PATH . "infotuts.csv"; // Name of your CSV file
$csvfile = fopen($csv_file, 'r');
$theData = fgets($csvfile);
$i = 0;
while (!feof($csvfile)) {
$csv_data[] = fgets($csvfile, 1024);
$csv_array = explode(",", $csv_data[$i]);
$insert_csv = array();
$insert_csv['test_id'] = $csv_array[0];
// $insert_csv['test_aw_id'] = $csv_array[1];
// $insert_csv['test_name'] = $csv_array[2];
$image_id = $csv_array[1];
$download_image = $csv_array[2];
// Store the original filename
$original_name = basename($download_image);
// Original extension by string manipulation
$original_extension = substr($original_name, strrpos($original_name, '.')); // ".jpg"
// An array to match mime types from finfo_file() with extensions
// Use of finfo_file() is recommended if you can't trust the input
// filename's extension
$types = array('image/jpeg' => '.jpg','image/png' => '.png','image/gif' => '.gif');
// Get the file and save it
$img = file_get_contents($download_image);
$stored_name = 'images/' . $image_id . $original_extension;
if ($img) {
file_put_contents($stored_name);
// Get the filesize if needed
$size = filesize($stored_name);
// If you don't care about validating the mime type, skip all of this...
// Check the file information
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $stored_name);
// Lookup the type in your array to get the extension
if (isset($types[$mimetype])) {
// if the reported type doesn't match the original extension, rename the file
if ($types[$mimetype] != $original_extension) {
rename($stored_name, 'images/' . $image_id . $types[$mimetype]);
}
}
else {
// unknown type, handle accordingly...
}
finfo_close($finfo);
$query = "INSERT INTO test(test_id, test_aw_id, test_name) VALUES ('', '$image_id', '$stored_name')";
$n=mysqli_query($con, $query);
$i++;
}
else {
echo 'Could not get file';
}
}
fclose($csvfile);
By retrieving the file with file_get_contents(), you won't get any particularly useful information about its format. It carries no metadata similar to that found in $_FILES for upload.
If the image URLs are expected to be a full filename with an extension, and you trust the extension to be correct, you may use that as your type. However, finfo_file() with the FILEINFO_MIME_TYPE option will probe the file to return its mime type, as in image/jpeg or image/png.
So your workflow will be to:
Retrieve the image with file_get_contents()
Save it to your local filesystem with its new name
Call finfo_file() to retrieve its mime type
Update your database with the desired details.
Example:
// Assume this URL for $download_image from your CSV
$download_image = 'http://example.com/images/img1.jpg';
$image_id = 12345;
// Store the original filename
$original_name = basename($download_image); // "img1.jpg"
// Original extension by string manipulation
$original_extension = substr($original_name, strrpos($original_name, '.')); // ".jpg"
// An array to match mime types from finfo_file() with extensions
// Use of finfo_file() is recommended if you can't trust the input
// filename's extension
$types = array(
'image/jpeg' => '.jpg',
'image/png' => '.png',
'image/gif' => '.gif'
// Other types as needed...
);
// Get the file and save it
$img = file_get_contents($download_image);
$stored_name = 'images/' . $image_id . $original_extension;
if ($img) {
file_put_contents($stored_name, $img);
// Get the filesize if needed
$size = filesize($stored_name);
// If you don't care about validating the mime type, skip all of this...
// Check the file information
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $stored_name);
// Lookup the type in your array to get the extension
if (isset($types[$mimetype])) {
// if the reported type doesn't match the original extension, rename the file
if ($types[$mimetype] != $original_extension) {
rename($stored_name, 'images/' . $image_id . $types[$mimetype]);
}
}
else {
// unknown type, handle accordingly...
}
finfo_close($finfo);
// Now save all the extra info you retrieved into your database however you normally would
// $mimetype, $original_name, $original_extension, $filesize
}
else {
// Error, couldn't get file
}
If you want to get the mimetype string from the extension you already have, and aren't validating the type with finfo, you can flip the $types to swap keys with values.
if (in_array($original_extension), $types) {
$mimetype = array_flip($types)[$original_extension];
}
<?php
include_once('includes/functions.php');
define('CSV_PATH','E:/xampp/htdocs/aff/csv-import/');
$csv_file = CSV_PATH . "infotuts.csv";
$csvfile = fopen($csv_file, 'r');
$theData = fgets($csvfile);
$i = 0;
while (!feof($csvfile)) {
$csv_data[] = fgets($csvfile, 1024);
$csv_array = explode(",", $csv_data[$i]);
$insert_csv = array();
$insert_csv['test_id'] = $csv_array[0];
$insert_csv['test_aw_id'] = $csv_array[1];
$insert_csv['test_name'] = $csv_array[2];
$image_id = $insert_csv['test_aw_id'];
$download_image = $insert_csv['test_name'];
$original_name = basename($download_image);
$original_extension = substr($original_name, strrpos($original_name, '.')); // ".jpg"
$types = array('image/jpeg' => '.jpg','image/png' => '.png','image/gif' => '.gif');
$img = file_get_contents($download_image);
$stored_name = $image_id . $original_extension;
$stored_name = trim($stored_name);
if ($img) {
file_put_contents($stored_name, $img);
//$size = filesize($stored_name);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $stored_name);
if (isset($types[$mimetype])) {
if ($types[$mimetype] != $original_extension) {
rename($stored_name, 'E:/xampp/htdocs/aff/images/products/' . $stored_name);
}
}
else {
}
finfo_close($finfo);
$query = "INSERT INTO test(test_id, test_aw_id, test_name) VALUES ('', '$image_id', '$stored_name')";
$n=mysqli_query($con, $query);
$i++;
}
else {
echo 'Could not get file';
}
}
fclose($csvfile);
echo "File data successfully imported to database!!";
mysqli_close($con);
?>
I used this code to check for the type of images,
$f_type=$_FILES['fupload']['type'];
if ($f_type== "image/gif" OR $f_type== "image/png" OR $f_type== "image/jpeg" OR $f_type== "image/JPEG" OR $f_type== "image/PNG" OR $f_type== "image/GIF")
{
$error=False;
}
else
{
$error=True;
}
but some users complain they get an error while uploading any type of images, while some others don't get any errors!
I was wondering if this fixes the problem:
if (mime_content_type($_FILES['fupload']['type']) == "image/gif"){...
Any comments?
Never use $_FILES..['type']. The information contained in it is not verified at all, it's a user-defined value. Test the type yourself. For images, exif_imagetype is usually a good choice:
$allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF);
$detectedType = exif_imagetype($_FILES['fupload']['tmp_name']);
$error = !in_array($detectedType, $allowedTypes);
Alternatively, the finfo functions are great, if your server supports them.
In addition to #deceze, you may also finfo() to check the MIME-type of non-image-files:
$finfo = new finfo();
$fileMimeType = $finfo->file($path . $filename, FILEINFO_MIME_TYPE);
Sure you could check if it's an image with exif, but a better way I think is to do with finfo like this:
$allowed_types = array ( 'application/pdf', 'image/jpeg', 'image/png' );
$fileInfo = finfo_open(FILEINFO_MIME_TYPE);
$detected_type = finfo_file( $fileInfo, $_FILES['datei']['tmp_name'] );
if ( !in_array($detected_type, $allowed_types) ) {
die ( 'Please upload a pdf or an image ' );
}
finfo_close( $fileInfo );
The best way in my opinion is first to use getimagesize() followed by imagecreatefromstring().
$size = getimagesize($filename);
if ($size === false) {
throw new Exception("{$filename}: Invalid image.");
}
if ($size[0] > 2500 || $size[1] > 2500) {
throw new Exception("{$filename}: Image too large.");
}
if (!$img = #imagecreatefromstring(file_get_contents($filename))) {
throw new Exception("{$filename}: Invalid image content.");
}
Checking by getimagesize() prevents some DoS attacks, because we don't have to try to imagecreatefromstring() from every file provided by the user, either non-image file or file too big. Unfortunately, according to PHP docs cannot be relied on for checking image type content.
The imagecreatefromstring() finally tries to open the file as an image - if is succeeds - we have an image.
This is a simple, one line script that I use often.
$image = "/var/www/Core/temp/image.jpg";
$isImage = explode("/", mime_content_type())[0] == "image";
Basically I am using mime_content_type() to get something like "image/jpg" and then exploding it by "/" and checking against the first element of the array to see if it says "image".
I hope it works!
In PHP 5.5 I use this function for getting file type and check if image:
function getFileType( $file ) {
return image_type_to_mime_type( exif_imagetype( $file ) );
}
// Get file type
$file_type = getFileType( 'path/to/images/test.png' );
echo $file_type;
// Prints image/png
// 1. All images have mime type starting with "image"
// 2. No other non-image mime types contain string "image" in it
Then you could do:
if ( strpos( $filetype, 'image' ) !== false ) {
// This is an image
}
Complete list of mime types: http://www.sitepoint.com/web-foundations/mime-types-complete-list/
That last line is close. You can use:
if (mime_content_type($_FILES['fupload']['tmp_name']) == "image/gif"){...
In the case I'm currently working on, my $_FILES..['type'] reports itself as "text/csv", while both mime_content_type() and finfo() (suggested by others) report "text/plain.". As #deceze points out, $_FILES..['type'] is only useful to know what type a client thinks a file is.
you can try this
$file_extension = explode('.',$file['name']);
$file_extension = strtolower(end($file_extension));
$accepted_formate = array('jpeg','jpg','png');
if(in_array($file_extension,$accepted_formate)) {
echo "This is jpeg/jpg/png file";
} else {
echo $file_extension.' This is file not allowed !!';
}
WARNING: the following answer does not actually check the file type. It only checks the name. It is not suitable for actual security purposes.
EDIT: Don't Use this method as it serves no security check. I am leaving this answer here so that no one makes the same mistake like me by trying this.
I tried the following and it worked for me:
$allowed = array('gif','png' ,'jpg', 'pdf');
$filename = $_FILES['input_tag_name']['name'];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if(!in_array($ext,$allowed) ) {
echo 'error';
}
Source link
how to check whether file is image or video type in php version 5.2.9
$mime = mime_content_type($file);
if(strstr($mime, "video/")){
// this code for video
}else if(strstr($mime, "image/")){
// this code for image
}
Should work for most file extentions.
See my answer to
How can I check if a file is a mp3 or image file?
Example Code
function getMimeType($filename)
{
$mimetype = false;
if(function_exists('finfo_fopen')) {
// open with FileInfo
} elseif(function_exists('getimagesize')) {
// open with GD
} elseif(function_exists('exif_imagetype')) {
// open with EXIF
} elseif(function_exists('mime_content_type')) {
$mimetype = mime_content_type($filename);
}
return $mimetype;
}
I use the following code which IMO is more universal than in the first and the most upvoted answer:
$mimeType = mime_content_type($filename);
$fileType = explode('/', $mimeType)[0];
I hope it was helpful for anyone.
You can check the MIME type using the finfo_file function
Example from the help page
<?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);
?>
EDIT: after better checking your question, this won't work, finfo functions require PHP 5.3.0
if(isset($_FILES['my_file'])) {
$mime = $_FILES['my_file']['type'];
if(strstr($mime, "video/")){
$filetype = "video";
}else if(strstr($mime, "image/")){
$filetype = "image";
}else if(strstr($mime, "audio/")){
$filetype = "audio";
}
Rather old question, but for others looking at this in the future, I would handle this like so:
function getType($file): string
{
$mime_type = mime_content_type($file);
return strtok($mime_type, '/');
}
This method utilises strtok to return the portion of the $mime_type string before the first /.
For example, let's say $file has a $mime_type of video/mp4, the getType method will return video.
I use this code and it works very well.
$mimeType = $request->images->getMimeType();
$fileType = explode('/', $mimeType)[0];
if it was an image, this code will give you the image word in the $fileType and if it was a video this code will give you the video word in the $fileType, then you can check on it by the if conditions.
good luck