-1

When I download a blob image from my database its size is 1 KB. When I open the .png file itself, the image is not appearing. The image size appears in my MySQL database table. I couldn't figure out why it downloads an empty file from my database while the name and filetype are showing up correctly.

My table columns

Enter image description here

Everything seems to be correct with name, filetype, and size.

Enter image description here

File Upload.php

<?php
    require('config.php');
    session_start();
    if(isset($_POST['save']))
    {
        $target_dir = "upload/img/";

        $filename = explode('.', $_FILES['image']['name']);
        $ext = $filename[1];
        $imgname = time() . '.' . $ext;
        $target_file = $target_dir . $imgname;

        $uploadOk = 1;
        $imageFileType = pathinfo($target_file, PATHINFO_EXTENSION);
        // Check if image file is a actual image or fake image
        $check = getimagesize($_FILES["image"]["tmp_name"]);
        if($check !== false) {
            $text = "File is an image - " . $check["mime"] . ".";
            $uploadOk = 1;
        } else {
            $text = "File is not an image.";
            $uploadOk = 0;
        }
        // Check if file already exists
        if(file_exists($target_file)) {
            $text = "Sorry, file already exists.";
            $uploadOk = 0;
        }
        // Check file size
        if($_FILES["image"]["size"] > 2000000) {
            $text = "Sorry, your file is too large.";
            $uploadOk = 0;
        }
        // Allow certain file formats
        if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" &&
           $imageFileType != "gif" && $imageFileType != "bmp" ) {

            echo "Sorry, only JPG, JPEG, PNG, GIF & BMP files are allowed.";
            $uploadOk = 0;
        }
        // Check if $uploadOk is set to 0 by an error
        if($uploadOk == 0) {
            $_SESSION["error"] = $text;
            header("Location:index.php?id=$id"); /* Redirect browser */
            exit();

        // If everything is OK, try to upload the file
        }else {
            if (move_uploaded_file($_FILES["image"]["tmp_name"], $target_file)) {
                $path = $imgname;
                $finfo = new finfo();
                $array = explode('.', $_FILES['image']['name']);
                $extension = end($array);
                $filesize = $_FILES["image"]["size"];

                $conn->query("INSERT INTO images (image,name,filetype,size) VALUES ('$path','$path','$extension','$filesize')");
                $_SESSION["Success"] = 'Upload success';
                header("Location:index.php"); /* Redirect browser */
                exit();
            } else {
                $_SESSION["err"] = $text;
                header("Location:index.php"); /* Redirect browser */
                exit();
            }
        }
    }
?>

File Download.php

<?php
    // Include configuration file
    require_once 'config.php';

    $id = $_GET["id"];
    $sql = "select * from images where id=$id "; // 1
    $res = $conn->query($sql);
    while($row = $res->fetch_assoc())
    {
        $image = $row['image'];
        $name = $row['name'];
        $type = $row['filetype'];
        $size =  $row['size'];
    }

    header("Content-type: " . $type);
    header('Content-Disposition: attachment; filename="' . $name . '"');
    header("Content-Transfer-Encoding: binary");
    header('Expires: 0');
    header('Pragma: no-cache');
    header("Content-Length: " . $size);

    echo $image;
    exit();
?>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
in2d
  • 544
  • 9
  • 19
  • 3
    `$path` is essentially `time().'.'.$ext;` which is a path (hence the 14bytes) why you storing it as blob? – Lawrence Cherone Nov 27 '17 at 16:57
  • 3
    `$image` is basically the name of the file (that's what you store in the `image` field). You need to read the file from the file system where you saved it using the path and send its content to the client. Also, your content type is not accurate, you need to get the proper mime type, not just the extension. I think you mixed up the upload and download php codes from wherever you download them from. The upload code is for saving data into the file system and linking to it, while the download one is for getting the image data out of the database. – Shadow Nov 27 '17 at 17:10
  • For locating the PHP error log, the canonical is *[Where does PHP store the error log? (PHP 5, Apache, FastCGI, and cPanel)](https://stackoverflow.com/questions/5127838/)* (despite the over-specific title). – Peter Mortensen Sep 26 '21 at 13:54

1 Answers1

1

Your screenshot of the database shows your image blob being 14 bytes only. This is simply the name of the file:

 $conn->query("INSERT INTO images (image, name,filetype,size)
               VALUES ('$path','$path','$extension','$filesize')");

Here is your problem. You are inserting the file name as the file data.

Simply replace your first instance of $path with the contents of the file:

 $fileData = file_get_contents($target_file);
 $conn->query("INSERT INTO images (image, name,filetype,size)
               VALUES ('$fileData','$path','$extension','$filesize')");

Stop using content-length in you header. It is fraught with problems when using PHP with downloading files. Just don't use it and let the browser accept as much data as the server will give it.

The issue is the way PHP reads the filesize on some systems, and passes that data to the header, but the header is accepting either filesizes which are a bit larger (~5%) due to how the diskspace is read by different programs, or totally different due to the server auto-compressing the file in transfer (gzip).

(For all intents and purposes, from the viewpoint of the web server/browser, the blob data is a file.)


As referenced by Shadow, your content type header is also incorrect.

 header("Content-type: " . $type); // Wrong $type.

It should be a recognised MIME type such as image/jpeg, so $extension = end($array); should be replaced by something such as mime_content_type():

 $extension = mime_content_type($target_file)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Martin
  • 22,212
  • 11
  • 70
  • 132
  • 1
    It would be appreciated if the `-1` poster removed their mark down or explained why it should be retained? I have updated my answer so feel it no longer needs the -1. Cheers – Martin Nov 27 '17 at 17:14
  • Thank you for your answer. When i tryed this it uploads everything else except the image to my database. – in2d Nov 27 '17 at 17:23
  • 2
    There are numerous issues with your code. You would do well to [read your PHP error logs](https://stackoverflow.com/questions/8667190/get-php-error-log-from-php). – Martin Nov 27 '17 at 17:26
  • Where am i supposed to add those? And where would the errors appear? – in2d Nov 27 '17 at 18:31
  • Also my website shows text like this "�Q��2��V4 �"�TT� �DQGA�/Q�׈" when i upload a image now. – in2d Nov 27 '17 at 18:32
  • 1
    @in2d there are simply too many things that are wrong with your code (and frankly, with this answer as well). I would discard it completely and start from scratch. – Shadow Nov 27 '17 at 19:53