0

I am new to php. Written some php code to upload, view and download from mysql db. Everything is working well except download. When downloading a file, its downloaded but empty when opened. I am uploading and downloading directly from db. No local files in filesystem. Please help.

Upload code :

<?php
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['upload'])) {
        if ($_FILES['upload_file1']['size'] <= 0) {
            echo 'Hey, Please choose at least one file';
        } else {
            foreach ($_FILES as $key => $value) {
                if (0 < $value['error']) {
                    echo 'Error during file upload ' . $value['error'];
                } else if (!empty($value['name'])) {
                    $dbConn = mysqli_connect('localhost', 'root', '', 'files') or die('MySQL connect failed. ' . mysqli_connect_error());
                    
                    $sql = "insert into files_data(name, type, size, content, saved_date) values('".$value['name']."', '".$value['type']."', '".filesize_formatted($value['size'])."', '".mysqli_escape_string($dbConn, file_get_contents($value['tmp_name']))."', '".date('Y-m-d H:i:s')."')";
                    
                    $result = mysqli_query($dbConn, $sql) or die(mysqli_error($dbConn));
                    
                    if($result) {
                        echo 'File successfully saved to database';
                    }
                }
            }
        }
    }
    
    function filesize_formatted($size) {
        $units = array( 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
        $power = $size > 0 ? floor(log($size, 1024)) : 0;
        
        return number_format($size / pow(1024, $power), 2, '.', ',') . ' ' . $units[$power];
    }
    ?>

SQL code:

CREATE TABLE `files_data` (
  `id` int unsigned COLLATE utf8mb4_unicode_ci NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `type` varchar(25) COLLATE utf8mb4_unicode_ci NOT NULL,
  `size` varchar(25) COLLATE utf8mb4_unicode_ci NOT NULL,
  `content` blob NOT NULL,
  `saved_date` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

fetching code:

<table class="table table-bordered">
            <tr>
                <th>PDF</th>
            </tr>
            <?php  
                include 'dbconfig.php';
                $query = "SELECT * FROM files_data ORDER BY id DESC";  
                $result = mysqli_query($connect, $query); 
                $row = mysqli_num_rows($result) ;
                for($i=0;$i<$row;$i++){
                    $arr = mysqli_fetch_assoc($result);
                    $fileName = $arr['name'];
                    $fileContent = $arr['content'];
                ?>
            <tr>
                <td>
                    <a href="download.php?file=<?php echo $arr['id']; ?>"><?php echo $fileName; ?></a>
                </td>
            </tr>

            <?php   } ?>

        </table>

Download code:

<?php
include 'dbconfig.php';
mysqli_set_charset($connect,'utf-8');
$id = $_GET['file'];
$query = "SELECT * " ."FROM files_data WHERE id = '$id'";
$result = mysqli_query($connect,$query) 
       or die('Error, query failed');
list($id, $file, $type, $size,$content) = mysqli_fetch_array($result);
header("Content-length: $size");
header("Content-type: $type");
header("Content-Disposition: attachment; filename=$file");
ob_clean();
flush();
echo $content;
mysqli_close($connection);
exit;

?>

DB table:

enter image description here

8
  • Are those backticks on the lines below mysqli_set_charset and above ob_clean there in the actual code? If so, you should be seeing a syntax error in your logs. Either way, have you checked those logs to see if there are any errors? Commented Jul 12, 2022 at 18:31
  • This looks like production code .. You really need to consider Prepared Statements Commented Jul 12, 2022 at 18:31
  • No the backticks are not in the actual code . I mentioned them manually. Commented Jul 12, 2022 at 18:33
  • @Zak I dont have knowledge about prepared statements Commented Jul 12, 2022 at 18:49
  • 1
    Then now is the right time to learn, before you get hacked. See also stackoverflow.com/questions/60174/… Commented Jul 12, 2022 at 21:38

3 Answers 3

1

Because you are sending size in the header that is only some part of the file content is actually disposition in the file and that is why you are getting a corrupted file after downloading.

<?php
include 'dbconfig.php';
mysqli_set_charset($connect,'utf-8');
$id = $_GET['file'];
$query = "SELECT * " ."FROM files_data WHERE id = '$id'";
$result = mysqli_query($connect,$query) 
       or die('Error, query failed');
list($id, $file, $type, $size,$content) = mysqli_fetch_array($result);
//header("Content-length: $size");
header("Content-type: $type");
header("Content-Disposition: attachment; filename=$file");
ob_clean();
flush();
echo $content;
mysqli_close($connection);
exit;

?>
Sign up to request clarification or add additional context in comments.

3 Comments

Still showing error after download.
I have also tried with a image. After download and opening the image its displaying half of it. And pdf files are displaying error saying failed to load pdf content.
Do I need to make any other changes ?
1

in my local env. where I set this code up. I used LongBlob. So that entire file even if it is large, then also it can save without any issue.

Comments

0

Ok. The problem was with the db. We need to set the table field "content" type to longblob or the file will get corrupted during upload as it is larger in size and will not fully upload.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.