php mime类型 使用 PHP 将文件上传到 MySQL 数据库

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

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

在 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 表单:

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

请注意 元素的第三个属性,“enctype”。这告诉浏览器如何将表单数据发送到服务器。实际上,在发送文件时,必须将其设置为“多部分/表单数据”。

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

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

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

在阶段 1 中构建的窗体中,我们将操作属性设置为“add_file.php”。这是我们将在该过程的这一阶段构建它的文件。

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

<?php// Check if a file has been uploadedif(isset($_FILES['uploaded_file'])) {// Make sure the file was sent without errorsif($_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 successfullif($result) {echo 'Success! Your file was successfully added!';        }else {echo 'Error! Failed to insert the file'. "
{$dbLink->error}

";} }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 pageecho '

Click here to go back

阶段 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 successfullif($result) {// Make sure there are some files in thereif($result->num_rows == 0) {echo '

There are no files in the database

'
;
}else {// Print the top of a tableecho ''; // Print each filewhile($row = $result->fetch_assoc()) {echo ""; } // Close tableecho '
NameMimeSize (bytes)Created 
{$row['name']}{$row['mime']}{$row['size']}{$row['created']}Download
'
;
} // Free the result$result->free();}else{echo 'Error! SQL query failed:';echo "
{$dbLink->error}

";}// Close the mysql connection$dbLink->close();?>

第 4 阶段:下载文件

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

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

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

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

<?php// Make sure an ID was passedif(isset($_GET['id'])) {// Get the ID$id = intval($_GET['id']); // Make sure the ID is in fact a valid IDif($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 validif($result->num_rows == 1) {// Get the row$row = mysqli_fetch_assoc($result); // Print headersheader("Content-Type: ". $row['mime']);header("Content-Length: ". $row['size']);header("Content-Disposition: attachment; filename=". $row['name']); // Print dataecho $row['data'];            }else {echo 'Error! No image exists with that ID.';            } // Free the mysqli resources@mysqli_free_result($result);        }else {echo "Error! Query failed: 
{$dbLink->error}

";}@mysqli_close($dbLink); }}else {echo 'Error! No ID was passed.';}?>

任何像样的浏览器都应该能够读取标题并了解这是什么类型的文件,并且要下载而不是打开它。

终点线

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

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

我希望这有所帮助,并祝你一切顺利。

原创文章,作者:筱凯,如若转载,请注明出处:https://www.jingyueyun.com/ask/206.html

(1)
筱凯筱凯
上一篇 2024 年 7 月 10 日
下一篇 2024 年 7 月 10 日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

云产品限时秒杀。精选云产品高防服务器,500M大带宽限量抢购  >>点击进入