您可能想知道为什么要将文件“放入”数据库,而不是仅仅放入文件系统。 好吧,在大多数时候,你不会。
在您的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> </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
修订版- 2008年8月20日 -用改进的mysqli函数替换了旧的mysql函数。
- 2009年12月12日 -更新了简介,以详细介绍此方法的优缺点。 代码结构也有所改善。 将mysqli程序函数替换为其对应的OOP。 (感谢kovik指出需要进行这些更改!)
From: https://bytes.com/topic/php/insights/740327-uploading-files-into-mysql-database-using-php
本文详细介绍了如何使用PHP将文件上传至MySQL数据库,包括数据库设计、文件上传、数据库插入及文件下载等步骤。
216

被折叠的 条评论
为什么被折叠?



