简体   繁体   中英

Validating avatar images with PHP

I have a column in a MySQL database called photo of type mediumblob and it can be NULL .

This should represent a small photo of an employee displayed in the top right corner of web application.

The new employee is inserted via a form to MySQL database.

<form action="insert" method="post" enctype="multipart/form-data">
   ...
   <label for="photo">Photo</label>
   <input type="file" name="photo">
   ...
</form>

The photo will be validated as follows:

  1. It can be unuploaded (no photo will be provided in the form)

    else if some photo is provided

  2. It should be of image type
  3. The image size should be suitable size for this purpose
  4. The dimensions of the image should be suitable for this purpose

Here is the outline of my validation code so far. I have already created some validation conditions (1 and 2). Are those OK? And don't know how to create conditions 3 and 4.

$file = $_FILES['photo']['tmp_name']
if (!isset($file))
{
    $image = ""; // 1), empty string will be inserted into the database
}
else {
    $image = addslashes(file_get_contents($_FILES['photo']['tmp_name']));
    $image_size = getimagesize($_FILES['photo']['tmp_name']);

    if ($image_size == FALSE) { 
      // 2) not an image file
      // display the form again with error message
    }

    // checking 3)
    // checking 4)
}

For condition 3 u can use:

 $filesize = filesize($filename); u get size of the file in bytes. For condition 4 u can use: list($width, $height) = getimagesize($_FILES['photo']['tmp_name']); where $width and $height is the dimension of image. 

Here are some helpful tips packed into code:

$upload_error = isset( $_FILES['photo']['error'] ) ? $_FILES['photo']['error'] : UPLOAD_ERR_NO_FILE;
if ($upload_error == UPLOAD_ERR_NO_FILE) {
    // 1) No file uploaded
    $image = null; // I changed the empty string into a null, to avoid the mediumblob allocating space for the empty string
} elseif ($upload_error) {
    // 5) You forgot to check if the file upload failed
    switch ($upload_error) {
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            $message = "file_too_big";
            break;
        case UPLOAD_ERR_PARTIAL:
            $message = "upload_not_complete";
            break;
        case UPLOAD_ERR_EXTENSION:
            $message = "bad_file_extension";
            break;
        case UPLOAD_ERR_NO_TMP_DIR:
        case UPLOAD_ERR_CANT_WRITE:
            $message = "internal_upload_error";
            break;
        default:
            $message = "unknown_upload_error";
            break;
    } 
    header("Location: form.php?error=$message"); // Load form again and show error
    exit;
} else {
    $file = $_FILES['photo']['tmp_name'];
    $file_size = $_FILES['photo']['size'];
    if ($file_size > 5242880) { // 5 Megabyte for example, but always less than 16 Megabytes, because you use mediumblob
        // 3) The image size is not suitable for this purpose
        header("Location: form.php?error=file_too_big"); // Load form again and show error
        exit;
    }
    $image_size = getimagesize($file);
    if ($image_size) {
        $width = $image_size[0];
        $height = $image_size[1];
        if ($width < 100 || $width > 1000 || $height < 100 || $height > 1000) {
            // 4) Image dimensions are not suitable. Width/height are not between 100 and 1000 pixels
            header("Location: form.php?error=dimensions_not_ok"); // Load form again and show error
            exit;
        }
    } else {
        // 2) Not an image type
        header("Location: form.php?error=not_an_image"); // Load form again and show error
        exit;
    }
    $image = file_get_contents($file);
}
// now escape $image and save it to the database
// But I suggest you not use addslashes() to escape binary data
// Use parameterized queries / mysqli_real_escape_string() / mysql_real_escape_string() instead

Use Best way to determine if a file is empty (php)? for point 1
Point two is not complete at all (not secure):
Eg add an extension check: PHP check file extension
More security tips for point 2: http://nullcandy.com/php-image-upload-security-how-not-to-do-it/
Point 3 and 4 can be covered with getimagesize() and filesize()
Get image dimensions
http://php.net/manual/en/function.filesize.php

Your code is ok, you just need to add following lines to fulfil all your requirements:

$image="";
if (isset($_FILES["photo"]) && $_FILES["photo"]["error"] < 1){
    $file = $_FILES['photo']['tmp_name'];
    $imageInfo = getimagesize($file);
    if(is_array($imageInfo)){
         if($imageInfo[0]>30 && $imageInfo[0]<257 && $imageInfo[1]>30 && $imageInfo[1]<257){
           //$imageInfo[0] is width and $imageInfo[1] is height, you can set limit according to your need. I set it to MIN: 31*31 AND MAX 256*256
           // if you want square image then add " && $imageInfo[0]=$imageInfo[1]" in above-if-clause

              $imageSize=filesize($file); //returns bytes in integer
              if($imageSize> 250 && $imageSize<20481) // image size should be less then 20kb
                  $image = addslashes(file_get_contents($file));
              else echo "Image file should not grater then 20 KB.";
         }
         else echo "Image dimension(width*height) should be 31*31 to 256*256.";
    }
    else echo "Wrong file. Upload a Image file.";
}
else echo "No file uploaded or Error in file uploaded.";

if(trim($image)==""){
   //display form again
}
      $userfile_name = $_FILES['image']['name'];
         $userfile_tmp = $_FILES['image']['tmp_name'];
         $userfile_size = $_FILES['image']['size'];
         $filename = basename($_FILES['image']['name']);
         $allowedExts = array("gif", "jpeg", "jpg", "png");
         $extension = end(explode(".", $_FILES["image"]["name"]));
         if(($userfile_size / 1024) < 4096){
             if (isset($_FILES['image']['name']) && !empty($_FILES["image"]) && ($_FILES['image'] ['error'] == 0) && ($userfile_size / 1024 < 4096 ) && (($_FILES["image"]["type"] == "image/gif")
        || ($_FILES["image"]["type"] == "image/jpeg")
        || ($_FILES["image"]["type"] == "image/jpg")
        || ($_FILES["image"]["type"] == "image/pjpeg")
        || ($_FILES["image"]["type"] == "image/x-png")
        || ($_FILES["image"]["type"] == "image/png")) && in_array($extension, $allowedExts)) {
                        //Everything is ok, so we can upload the image.
        }else{
echo "Error in file Upload";
}
        }else{
    echo 'Oops!  Your file\'s size is to large.';
    }

For point 4, You need something that is executed on the client before the actual upload happens. With (server-side) php you can check the dimension only after the file has been uploaded

您可以使用以下PHP库: https : //github.com/codeguy/Upload

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM