I need to check whether a given image is a JPEG.
if ($_FILES["fname"]["error"] > 0) {
$imgData = "hyperlink/holder.jpg";
} else {
$imgData ="hyperlink/" . $_FILES["fname"]["name"];
}
// Only accept jpg images
// pjpeg is for Internet Explorer should be jpeg
if (!($_FILES["fname"]["type"] == "image/pjpeg") ) {
print "I only accept jpg files!";
exit(0);
}
When it goes to first statement in the first if statement it always gives I only accept jpg files!
How can I fix it?
Try the exif_imagetype image function.
Example:
if(exif_imagetype($filepath) != IMAGETYPE_JPEG){
echo 'Not a JPEG image';
}
PHP has such good image-type support, i wonder why you are restricting your app. In just a couple lines of code you can deal with any input format and convert to jpeg, if that is a requirement...
$im = imagecreatefrompng(input_filename)
imagejpeg($im, output_filename);
I believe the following works:
Also note that:
(exif_imagetype($ImagePathAndName) == IMAGETYPE_JPEG)
only reads the first few bytes looking for an image header so isn't really good enough to confirm if an image is corrupt.
Below I have it in a logical “and” statement i.e. both of these tests must be passed in order for the image to qualify as being valid and non-corrupt etc:
if ((exif_imagetype($ImagePathAndName) == IMAGETYPE_JPEG) && (imagecreatefromjpeg( $ImagePathAndName ) !== false ))
{
echo 'The picture is a valid jpg<br>';
}
Note: You need to place this line of code at the top of the php code in order to avoid seeing the warning messages from imagecreatefromjpeg( $ImagePathAndName ) when it encounters a fake/corrupt image file.
ini_set(‘gd.jpeg_ignore_warning’, 1);
Why don't you try creating an array of exceptions (the files you want the user to be able to upload).
// Hyperlink for your website
$hyperlink = "http://www.yourwebsitehere.com";
if($_FILES['fname']['error'] > 0)
{
$image= $hyperlink . "/holder.jpg";
}
else
{
$image = $hyperlink . "/" . $_FILES['fname']['name'];
}
// Only accept files of jpeg format
$exceptions = array("image/jpg", "image/jpeg", "image/pjpeg");
foreach($exceptions as $value)
{
if($_FILES['fname']['type'] != $value)
{
echo "I only accept jpeg images!";
break; // Or exit();
}
}
When using $_FILES, you are relying on informations sent by the client, which is not the best thing to do (you've seen it's not always the same, and, if I remember correctly, $_FILES['...']['type'] can be faked).
If you are using PHP >= 5.3 (or can install PECL packages), maybe you can give a look to the extension Fileinfo. If you are using an older version, what about mime_content_type?
And, as said by Scott, why allow only jpeg?
Looking about the code better : when you are in the first case (error > 0), you are assigning a default file to $imgData? Why the spaces around "hyperlink"?
And why do you always use to check the content-type, even if there was an error a couple of lines before?
To finish, did you have a look at the manual (Handling file uploads)?
Check the mime (Multipurpose Internet Mail Extensions) type of file with this code. And verify your desired type. You can also detect png,gif with this code.
if($_FILES["fname"]["type"] == "image/jpeg")
{
echo "File type is JPEG";
}
Related
I could of course check mime types through the exif_imagetype or getimagesize and check mime types one by one... But I just want ANY image - I dont care what type... So I was wondering - can I do something like this: ?
// PHP manual says: Determine the type of an image
// and that Imagetype Constants are 1-17 so :
$tmp_imagetype = exif_imagetype('image.gif');
if ( ($tmp_imagetype>=1) && ($tmp_imagetype<=17) ) {
echo "It is an image!";
} else{
echo "It isn't an image.";
}
Can I rely on that?
What happens when the file is not an image? Will it just return non-image constant value or will it throw a warning or error
Thanks
You really don't need all that you just need the following as exif_imagetype returns false if its not an image
if($imagetype = exif_imagetype('image.gif')){
// its an image
} else {
// its not an image
}
You could check if the function returns (exactly) FALSE:
$file="SOMEFILE";
if(exif_imagetype($file)===FALSE){
print("NOT IMAGE");
}else{
print("IMAGE");
}
Why don't you just put all types of images in an array and then check it with this code:
if(in_array($value, $array)) {
//it's an image! Hooray!
}else {
//it's not.
}
I have following script:
function listFolderFiles($dir){
$ffs = scandir($dir);
echo '<ol>';
foreach($ffs as $ff){
if($ff != '.' && $ff != '..'){
echo '<li>'.$ff;
if(is_dir($dir.'/'.$ff)) listFolderFiles($dir.'/'.$ff);
echo '</li>';
}
}
echo '</ol>';
}
listFolderFiles('upload');
My question is I want to detect a file is video(mp4 or mov)type, How i can detect $ff is a video type or not?
// Type contains video/mp4,video/avi,video/mpeg,video/mpg etc
if(preg_match('/video\/*/',$_FILES['add_image_image']['type'])):
echo "THIS IS A VIDEO FILE";
else:
echo "NOT A VIDEO FILE";
endif;
if(end(explode(".",$ff)) =="mp4")
{
echo "its an mp4 movie";
}
There you go, for case insensitive version of the extension
<?php
$ff="abc.MP4";
if(strtolower(end(explode(".",$ff))) =="mp4")
{
echo "its an mp4 movie";
}
?>
Use mime_content_typemime_content_type php.net
if (mime_content_type($dir.'/'.$ff)=='video/mp4')
echo "its mp4";
I use this code:
$mimeType = mime_content_type(public_path('uploads/' . $file));
$fileType = explode('/', $mimeType)[0]; // video|image
if ($fileType === 'video') {
// do something
}
Please use a tool like file. This answer is security aware, and a general response to uploaded file types. The second advantage to using file is it will tell you more detail about the format used. There are alot of combinations of formats that may be legitimately stored inside a '*.mpg' file. You may not be able to deal with all of them.
I did a more detailed websearch, there is a list of duplicate text articles, but no reliable solutions posted. There is a "magic bytes" detector in the form of fileinfo. This is compiled into most recent versions of PHP (its a standard extension).
NB: mime_content_type() is deprecated. Again, if you need to, try fileinfo
You can achive with preg_match
if(preg_match('/^.*\.(mp4|mov)$/i', $filename)) {
echo $filename;
}
You can append another video ext like: (mp4|mov|mpg|mpeg|wmv|mkv)
You can also try this. Should be fairly accurate and performant
<?php
function isVideo($file) {
return is_file($file) && (0 === strpos(mime_content_type($file), 'video/'));
}
?>
I recently use this to get the file type i.e. image or video:
explode('/', $request->article_thumbnail->getMimeType())[0]
Get the mime type of the uploading file and check the type like below,
$mime = $file->getMimeType;
$videoJS = array('video/mp4','video/ogg','video/webm');
if(array_search($mime, $videoJS) !== false) {
//do upload
}
$fileType = exec( 'file --mime-type '.escapeshellarg($filePath)); //e.g. output -> /tmp/somefile.mov: video/quicktime
$fileType = substr($fileType, strpos($fileType, ": ") + 2); //strip away file path -> video/quicktime
$fileType = substr($fileType, 0,strpos($fileType, "/")); //strip away whatever video type -> video
if ($fileType == 'video') $fileType = 'im a video!';
This code uses unix 'file' command with the option --mime-type to minimize the output for easier parsing. Not sure if there is a better way of parsing the output.
Also make sure you have read permission of the file you are checking.
i have a edit page that allow users to upload a profile image using forms
but the problem is that i keep getting the the format is not acceptable even if the image type is one of the accepted format.
this is the code
if(isset($_POST['parse_var']) == "pic")
{
if(!$_FILES['fileField']['tmp_name'])
{
$errorMSG = '<font color= "#FF0000">Please browse for an Image Before you press the button.</font>';
}
else
{
$maxfilesize = 51200;//in bytes = 50kb
if($_FILES['fileField']['size']>$maxfilesize)
{
$errorMSG = '<font color="#FF0000">Your image was too large, please try again.</font>';
unlink($_FILES['fileField']['tmp_name']);
}
elseif(!preg_match("^.(gif|jpg|png)$/i^",$_FILES['fileField']['name']))
{
$errorMSG = '<font color="#FF0000">Your Image was not one of the accepted format, please try again</font>';
unlink($_FILES['fileField']['tmp_name']);
}
else
{
$newname = "image01.jpg";
$place_file = move_uploaded_file($_FILES['fileField']['tmp_name'],"members/$id/".$newname);
$message='<font color="#00FF00>Your Image has been upload successfully</font>';
}
}//end else
}//end if
Major problems:
a)
elseif(!preg_match("^.(gif|jpg|png)$/i^",$_FILES['fileField']['name']))
^---
you should not be using a regex metachar as the pattern delimiter. Try
preg_match('/\.(gif|jpg|png)$/i', ...) instead.
But in a bigger picture view, you shouldn't be matching on filenames at all. Filenames can be forged. You should be doing server-side MIME-type determination (e.g. via file_info()) instead.
b)
you are NOT properly checking for upload success. The presence of a ['tmp_name'] in the $_FILES array means NOTHING. failed uploads can STILL produce a tmp_name, yet you end up with garbage. Always use something like this:
if ($_FILES['fileField']['error'] !== UPLOAD_ERR_OK) {
die("Upload failed with error code " . $_FILES['fileField']['error']);
}
the error codes are defined here: http://php.net/manual/en/features.file-upload.errors.php
c) (minor)
you do no need to unlink the temp files. PHP does that automatically when the script exits.
d) (stylistically HUGE error)
font tags? in 2013? The 1990s called and want their HTML 1.0 back...
on a page, i have :
if (!empty($_FILES['logo']['name'])) {
$dossier = 'upload/';
$fichier = basename($_FILES['logo']['name']);
$taille_maxi = 100000;
$taille = filesize($_FILES['logo']['tmp_name']);
$extensions = array('.png', '.jpg', '.jpeg');
$extension = strrchr($_FILES['logo']['name'], '.');
if(!in_array($extension, $extensions)) {
$erreur = 'ERROR you must upload the right type';
}
if($taille>$taille_maxi) {
$erreur = 'too heavy';
}
if(!empty($erreur)) {
// ...
}
}
The problem is, if the users wants to edit information WITHOUT uploading a LOGO, it raises an error : 'error you must upload the right type'
So, if a user didn't put anything in the inputbox in order to upload it, i don't want to enter in these conditions test.
i tested :
if (!empty($_FILES['logo']['name']) and if (isset($_FILES['logo']['name'])
but both doesn't seems to work.
Any ideas?
edit : maybe i wasn't so clear, i don't want to test if he uploaded a logo, i want to test IF he selected a file to upload, because right now, if he doesn't select a file to upload, php raises an error telling he must upload with the right format.
thanks.
You can check this with:
if (empty($_FILES['logo']['name'])) {
// No file was selected for upload, your (re)action goes here
}
Or you can use a javascript construction that only enables the upload/submit button whenever the upload field has a value other then an empty string ("") to avoid submission of the form with no upload at all.
There is a section in php documentation about file handling. You will find that you can check various errors and one of them is
UPLOAD_ERR_OK
Value: 0; There is no error, the file uploaded with success.
<...>
UPLOAD_ERR_NO_FILE
Value: 4; No file was uploaded.
In your case you need code like
if ($_FILES['logo']['error'] == UPLOAD_ERR_OK) { ... }
or
if ($_FILES['logo']['error'] != UPLOAD_ERR_NO_FILE) { ... }
You should consider checking (and probably providing appropriate response for a user) for other various errors as well.
You should use is_uploaded_file($_FILES['logo']['tmp_name']) to make sure that the file was indeed uploaded through a POST.
I would test if (file_exists($_FILES['logo']['tmp_name'])) and see if it works.
Or, more approperately (thanks Baloo): if (is_uploaded_file($_FILES['logo']['tmp_name']))
We Could Use
For Single file:
if ($_FILES['logo']['name'] == "") {
// No file was selected for upload, your (re)action goes here
}
For Multiple files:
if ($_FILES['logo']['tmp_name'][0] == "") {
// No files were selected for upload, your (re)action goes here
}
if($_FILES["uploadfile"]["name"]=="") {}
this can be used
No file was selected for upload, your (re)action goes here in if body
echo "no file selected";
if ($_FILES['logo']['error'] === 0)
is the only right way
On the PHP website, the only real checking they suggest is using is_uploaded_file() or move_uploaded_file(), here. Of course you usually don't want user's uploading any type of file, for a variety of reasons.
Because of this, I have often used some "strict" mime type checking. Of course this is very flawed because often mime types are wrong and users can't upload their file. It is also very easy to fake and/or change. And along with all of that, each browser and OS deals with them differently.
Another method is to check the extension, which of course is even easier to change than mime type.
If you only want images, using something like getimagesize() will work.
What about other types of files? PDFs, Word documents or Excel files? Or even text only files?
Edit: If you don't have mime_content_type or Fileinfo and system("file -bi $uploadedfile") gives you the wrong file type, what other options are there?
Take a look at mime_content_type or Fileinfo. These are built-in PHP commands for determining the type of a file by looking at the contents of the file. Also check the comments on the above two pages, there are some other good suggestions.
Personally I've had good luck using something that's essentially system("file -bi $uploadedfile"), but I'm not sure if that's the best method.
IMHO, all MIME-type checking methods are useless.
Say you've got which should have MIME-type application/pdf. Standard methods are trying to find something that looks like a PDF header (%PDF- or smth. like that) and they will return 'Okay, seems like this is a PDF file' on success. But in fact this doesn't means anything. You can upload a file containing only %PDF-1.4 and it will pass MIME-check.
I mean if the file has an expected MIME-type - it will always pass the MIME-type check otherwise the result is undefined.
I assume you are going to have a fixed white-list of file-types that you will accept.
For each of these types, you are going to have to use different techniques to verify that they are valid examples of that format.
There are two related questions:
Does it look roughly like it might be the right type? (For JPEG, you could check the headers, as you mentioned. For many Unix-based formats, you could check the "magic cookie".)
Is it actually a valid example of that type (e.g. For any XML-like format, you could validate against a DTD.)
I think that, for each format, you should ask separate questions for each one, because the answer will be quite different for PDFs compared to ZIP files.
I used mime_content_type that is compatible with PHP 5.2, because I can use neither Fileinfo (it requires PHP 5.3) nor system(), that is disabled by my provider.
For example, I check if a file is a text file so:
if (strcmp(substr(mime_content_type($f),0,4),"text")==0) { ... }
You can see a full example in my "PHP Directory and Subdirectory Listener & File Viewer and Downloader" at:
http://www.galgani.it/software_repository/index.php
if(isset($_FILES['uploaded'])) {
$temp = explode(".", $_FILES["uploaded"]["name"]);
$allowedExts = array("txt","htm","html","php","css","js","json","xml","swf","flv","pdf","psd","ai","eps","eps","ps","doc","rtf","ppt","odt","ods");
$extension = end($temp);
if( in_array($extension, $allowedExts)) {
//code....
} else {
echo "Error,not Documentum type...";
}
}
Here is the function file_mime_type from iZend:
function file_mime_type($file, $encoding=true) {
$mime=false;
if (function_exists('finfo_file')) {
$finfo = finfo_open(FILEINFO_MIME);
$mime = finfo_file($finfo, $file);
finfo_close($finfo);
}
else if (substr(PHP_OS, 0, 3) == 'WIN') {
$mime = mime_content_type($file);
}
else {
$file = escapeshellarg($file);
$cmd = "file -iL $file";
exec($cmd, $output, $r);
if ($r == 0) {
$mime = substr($output[0], strpos($output[0], ': ')+2);
}
}
if (!$mime) {
return false;
}
if ($encoding) {
return $mime;
}
return substr($mime, 0, strpos($mime, '; '));
}
For PHP>=5.3.0, you can use php's finfo_file(finfo_file) function to get the file infomation about the file.
For PHP<5.3.0, you can use your's system's file command to get the file information.
So just make it in one function,
var_dump(mime_type("wiki templete.txt")); // print string(10) "text/plain"
function mime_type($file_path)
{
if (function_exists('finfo_open')) {
$finfo = new finfo(FILEINFO_MIME_TYPE, null);
$mime_type = $finfo->file($file_path);
}
if (!$mime_type && function_exists('passthru') && function_exists('escapeshellarg')) {
ob_start();
passthru(sprintf('file -b --mime %s 2>/dev/null', escapeshellarg($file_path)), $return);
if ($return > 0) {
ob_end_clean();
$mime_type = null;
}
$type = trim(ob_get_clean());
if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) {
$mime_type = null;
}
$mime_type = $match[1];
}
return $mime_type;
}
MimeTypes