使用PHP将文件上传到MySQL数据库

本文详细介绍了如何使用PHP将文件上传至MySQL数据库,包括数据库设计、文件上传、数据库插入及文件下载等步骤。
部署运行你感兴趣的模型镜像

您可能想知道为什么要将文件“放入”数据库,而不是仅仅放入文件系统。 好吧,在大多数时候,你不会。

在您的PHP应用程序需要存储整个文件的情况下,首选方法是将文件保存到服务器的文件系统中,并将文件的物理位置存储在数据库中。 通常认为这是最简单,最快的文件存储方式。

但是,在某些情况下,您可能希望将文件本身与数据库中的其他数据一起保留。 这使您-或更确切地说:MySQL-可以完全控制文件数据,而不仅仅是文件在服务器上的位置。

但是,此方法有一些缺点,例如; 降低了性能,并增加了PHP代码和数据库结构的复杂性。 这是您在实际应用中使用它之前应仔细考虑的事项。

话虽如此,本文演示了如何从浏览器将文件上传到MySQL,以及如何将文件发送回浏览器。

在你开始之前

为了顺利解决此问题,您应该熟悉以下内容:

战斗计划

与所有程序一样,在开始编写之前,我们需要提前计划。 就是这样,我们在写之前就知道要写什么。

在开始该程序之前,我们需要设计数据库。 这不是一个复杂的设计,因为我们不是在谈论创建一些复杂的归档系统。 我们只需要一个表,该表包含文件的BLOB字段和其他字段来存储文件的信息,例如名称,大小,类型。

接着。 该程序的第一阶段是将文件从用户那里获取到服务器上,PHP可以与该服务器进行交互。 这是该过程中最简单的部分,仅需要基本的HTML表单。

第二阶段涉及读取上载的文件,确保已成功上载并将其添加到数据库中。 这与将文件上传到文件系统时使用的过程类似,但使用的是MySQL函数而不是文件系统函数。

第三阶段是列出所有已上传并保存在数据库中的文件,以及一个链接,以便可以下载该文件。 唯一的问题是服务器上不存在该文件,因此我们如何创建指向该文件的链接? 这是第4阶段处理的问题,在第3阶段我们要做的就是创建一个链接,该链接的URL中嵌入了要下载的文件的ID。

第四部分(也是最后一部分)是有关此过程最令人困惑的部分。 我们提取文件并将其发送到客户端浏览器的部分。

我们首先使用MySQL函数以及阶段3发送的ID,以从数据库中获取文件数据。 然后,在最终发送文件内容之前,设置一些标头,以使浏览器知道预期的内容。

现在,使用此摘要作为指导,开始编写程序。

阶段0:建立资料库

数据库很简单。 一个表,带有用于文件数据的BLOB字段,而几个字段用于与文件有关的各种信息:


CREATE TABLE `file` (
    `id`        Int Unsigned Not Null Auto_Increment,
    `name`      VarChar(255) Not Null Default 'Untitled.txt',
    `mime`      VarChar(50) Not Null Default 'text/plain',
    `size`      BigInt Unsigned Not Null Default 0,
    `data`      MediumBlob Not Null,
    `created`   DateTime Not Null,
    PRIMARY KEY (`id`)
) 
如您所见,我们存储文件名,包括扩展名。

我们有mime类型,用于让浏览器知道我们正在处理哪种文件。

文件大小,以字节为单位。

最后是数据本身,位于MediumBlob字段中。

阶段1:上传文件

现在,我们需要从用户那里获取文件。 我们设计的表不需要用户提供任何其他信息,因此我们将使其变得简单,并创建一个HTML表单,其中仅包含一个“文件”输入字段和一个提交按钮:

<!DOCTYPE html>
<head>
    <title>MySQL file upload example</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
    <form action="add_file.php" method="post" enctype="multipart/form-data">
        <input type="file" name="uploaded_file"><br>
        <input type="submit" value="Upload file">
    </form>
    <p>
        <a href="list_files.php">See all files</a>
    </p>
</body>
</html>
请注意<form>元素的第三个属性“ enctype”。 这告诉浏览器如何将表单数据发送到服务器。 就这样,在发送文件时,必须将其设置为“ multipart / form-data”。

如果以其他任何方式设置或根本没有设置,则可能无法正确传输文件。

在底部,我们有一个指向第3阶段创建的列表的链接。

阶段2:将文件添加到数据库

在第1阶段构建的表单中,我们将action属性设置为“ add_file.php”。 这是我们在流程的此阶段要构建的文件。

此文件需要检查文件是否已上传,确保已上传且没有错误,然后将其添加到数据库中:


<?php
// Check if a file has been uploaded
if(isset($_FILES['uploaded_file'])) {
    // Make sure the file was sent without errors
    if($_FILES['uploaded_file']['error'] == 0) {
        // Connect to the database
        $dbLink = new mysqli('127.0.0.1', 'user', 'pwd', 'myTable');
        if(mysqli_connect_errno()) {
            die("MySQL connection failed: ". mysqli_connect_error());
        } 
        // Gather all required data
        $name = $dbLink->real_escape_string($_FILES['uploaded_file']['name']);
        $mime = $dbLink->real_escape_string($_FILES['uploaded_file']['type']);
        $data = $dbLink->real_escape_string(file_get_contents($_FILES  ['uploaded_file']['tmp_name']));
        $size = intval($_FILES['uploaded_file']['size']); 
        // Create the SQL query
        $query = "
            INSERT INTO `file` (
                `name`, `mime`, `size`, `data`, `created`
            )
            VALUES (
                '{$name}', '{$mime}', {$size}, '{$data}', NOW()
            )"; 
        // Execute the query
        $result = $dbLink->query($query); 
        // Check if it was successfull
        if($result) {
            echo 'Success! Your file was successfully added!';
        }
        else {
            echo 'Error! Failed to insert the file'
               . "<pre>{$dbLink->error}</pre>";
        }
    }
    else {
        echo 'An error accured while the file was being uploaded. '
           . 'Error code: '. intval($_FILES['uploaded_file']['error']);
    } 
    // Close the mysql connection
    $dbLink->close();
}
else {
    echo 'Error! A file was not sent!';
} 
// Echo a link back to the main page
echo '<p>Click <a href="index.html">here</a> to go back</p>';
?>  
阶段3:列出所有现有文件

因此,现在我们的数据库中有几个文件,我们需要创建文件列表并链接它们,以便可以下载它们:

<?php
// Connect to the database
$dbLink = new mysqli('127.0.0.1', 'user', 'pwd', 'myTable');
if(mysqli_connect_errno()) {
    die("MySQL connection failed: ". mysqli_connect_error());
} 
// Query for a list of all existing files
$sql = 'SELECT `id`, `name`, `mime`, `size`, `created` FROM `file`';
$result = $dbLink->query($sql); 
// Check if it was successfull
if($result) {
    // Make sure there are some files in there
    if($result->num_rows == 0) {
        echo '<p>There are no files in the database</p>';
    }
    else {
        // Print the top of a table
        echo '<table width="100%">
                <tr>
                    <td><b>Name</b></td>
                    <td><b>Mime</b></td>
                    <td><b>Size (bytes)</b></td>
                    <td><b>Created</b></td>
                    <td><b>&nbsp;</b></td>
                </tr>'; 
        // Print each file
        while($row = $result->fetch_assoc()) {
            echo "
                <tr>
                    <td>{$row['name']}</td>
                    <td>{$row['mime']}</td>
                    <td>{$row['size']}</td>
                    <td>{$row['created']}</td>
                    <td><a href='get_file.php?id={$row['id']}'>Download</a></td>
                </tr>";
        } 
        // Close table
        echo '</table>';
    } 
    // Free the result
    $result->free();
}
else
{
    echo 'Error! SQL query failed:';
    echo "<pre>{$dbLink->error}</pre>";
} 
// Close the mysql connection
$dbLink->close();
?>
阶段4:下载文件

这部分通常是最容易引起混乱的部分。

要真正了解其工作原理,您必须了解浏览器如何下载文件。 当浏览器从HTTP服务器请求文件时,服务器响应将包含有关其确切包含内容的信息。 这些信息位称为标头。 标头通常包含有关发送的数据类型,响应的大小以及文件名的信息。

当然还有很多其他标题,在这里我将不介绍它们,但是值得研究!

现在,这段代码。 我们仅从读取阶段3中的链接发送的ID开始。如果ID有效,我们将在接收到的ID的文件上获取信息,发送标题,最后发送文件数据:

<?php
// Make sure an ID was passed
if(isset($_GET['id'])) {
// Get the ID
    $id = intval($_GET['id']); 
    // Make sure the ID is in fact a valid ID
    if($id <= 0) {
        die('The ID is invalid!');
    }
    else {
        // Connect to the database
        $dbLink = new mysqli('127.0.0.1', 'user', 'pwd', 'myTable');
        if(mysqli_connect_errno()) {
            die("MySQL connection failed: ". mysqli_connect_error());
        } 
        // Fetch the file information
        $query = "
            SELECT `mime`, `name`, `size`, `data`
            FROM `file`
            WHERE `id` = {$id}";
        $result = $dbLink->query($query); 
        if($result) {
            // Make sure the result is valid
            if($result->num_rows == 1) {
            // Get the row
                $row = mysqli_fetch_assoc($result); 
                // Print headers
                header("Content-Type: ". $row['mime']);
                header("Content-Length: ". $row['size']);
                header("Content-Disposition: attachment; filename=". $row['name']); 
                // Print data
                echo $row['data'];
            }
            else {
                echo 'Error! No image exists with that ID.';
            } 
            // Free the mysqli resources
            @mysqli_free_result($result);
        }
        else {
            echo "Error! Query failed: <pre>{$dbLink->error}</pre>";
        }
        @mysqli_close($dbLink);
    }
}
else {
    echo 'Error! No ID was passed.';
}
?>
任何体面的浏览器都应该能够读取标题并了解该文件是什么类型的文件以及要下载的文件而不是打开文件。 终点线

因此,正如您所看到的,这并不像人们想象的那么复杂。

当然,该代码仅是出于演示目的而编写的,我不建议您在不增加一些额外安全性的情况下使用它。 未经编辑,此代码基本上将允许任何人将任何内容上传到您的服务器,这不是一个好主意!

希望对您有所帮助,并祝您一切顺利。

再见,

-AtliÞór

修订版
  • 20088月20日 -用改进的mysqli函数替换了旧的mysql函数。
  • 200912月12日 -更新了简介,以详细介绍此方法的优缺点。 代码结构也有所改善。 将mysqli程序函数替换为其对应的OOP。 (感谢kovik指出需要进行这些更改!)

From: https://bytes.com/topic/php/insights/740327-uploading-files-into-mysql-database-using-php

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值