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

alprazolam
  • 111
  • 1
  • 14
  • 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? – IMSoP Jul 12 '22 at 18:31
  • This looks like production code .. You really need to consider [Prepared Statements](https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php) – Zak Jul 12 '22 at 18:31
  • No the backticks are not in the actual code . I mentioned them manually. – alprazolam Jul 12 '22 at 18:33
  • @Zak I dont have knowledge about prepared statements – alprazolam Jul 12 '22 at 18:49
  • 1
    Then now is the right time to learn, before you get hacked. See also https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php – IMSoP Jul 12 '22 at 21:38
  • You inserted the data using `insert into files_data(name, type, size, content, saved_date)` - is that the actual order of columns in your table? If so, then I doubt that `list($id, $file, $type, $size,$content) = ...` with the result of your `SELECT *` query actually reads the values of the _correct_ columns into those variables. – CBroe Jul 13 '22 at 07:24
  • Yes, The order is correct. – alprazolam Jul 13 '22 at 07:32
  • Can anyone provide any working php code to upload and download blob files ? – alprazolam Jul 13 '22 at 08:06

3 Answers3

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;

?>
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.

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.

alprazolam
  • 111
  • 1
  • 14