gpt4 book ai didi

php - PHP如何将文件服务器中的文件链接到数据库中的信息

转载 作者:行者123 更新时间:2023-11-29 06:50:59 24 4
gpt4 key购买 nike

我是PHP的新手,我正尝试将文件上传到文件服务器并将文件信息上传到mysql数据库,我已经完成了文件服务器和数据库部分的上传,但是如果需要,我需要从我的文件服务器文件夹中检索特定文件的信息我单击该文件,我正在尝试获取该逻辑。如果对此有任何可靠的解决方案,请帮助我。 (如果我错了,请纠正我,我的想法是将文件路径和信息一起上载到数据库,这会给我解决方案吗?但是文件名可以重复)

最佳答案

我想写一个简短的(对我来说这是简短的)“答案”,以便总结我的观点。

创建文件存储系统时的一些“最佳实践”。文件存储是一个广泛的类别,因此您的里程可能因其中一些而异。将它们当作我发现的效果很好的建议。

档名
不要使用最终用户指定的名称存储文件。他们可以并且将使用各种使人痛苦的残酷角色。有些可能与'单引号一样糟糕,在Linux上基本上使单引号使它成为不可能,甚至无法(直接)删除文件。有些事情看起来很简单,例如一个空格,但是根据使用位置和服务器上的操作系统的不同,可能会出现one%20two.txtone+two.txtone two.txt的情况,这可能会或可能不会引起各种问题在您的链接中。

最好的办法是创建一个哈希,就像sha1这样的东西,就像{user_id}{orgianl_name}一样简单。用户名使它与其他用户文件名冲突的可能性降低。

如果某人上载更多文件,则我更喜欢使用file_hash('sha1', $contents)的方式,然后一旦您可以捕获到该文件(内容相同,则哈希相同)。但是,如果您希望拥有较大的文件,则可能需要对其进行一些基准测试,以查看其具有的性能类型。我主要处理小文件,因此可以正常工作。
-请注意,带有时间戳的文件仍可以保存,因为全名不同,但是它很容易看到,并且可以在数据库中进行验证。

不管您做什么,我都给它加上时间戳记time().'-'.$filename。这是有用的信息,因为它是创建文件的绝对时间。

至于用户提供的名称。只需将其存储在数据库记录中即可。这样,您可以向他们显示他们期望的名称,但是使用您知道的名称对于链接始终是安全的。

$ filename ='一些令人毛骨悚然的^ fileane.jpg';

$ext = strrchr($filename, '.');

echo "\nExt: {$ext}\n";

$hash = sha1('some crapy^ fileane.jpg');

echo "Hash: {$hash}\n";

$time = time();

echo "Timestamp: {$time}\n";

$hashname = $time.'-'.$hash.$ext;

echo "Hashname: $hashname\n";


up

Ext: .jpg
Hash: bb9d2c2c7c73bb8248537a701870e35742b41c02
Timestamp: 1511853063
Hashname: 1511853063-bb9d2c2c7c73bb8248537a701870e35742b41c02.jpg


您可以尝试 here

路径永远不会存储文件的完整路径。您在数据库中所需要做的就是创建哈希名称的哈希。文件所在文件夹的“根”路径应使用PHP完成。这有几个好处。


防止目录传输。因为您没有绕过路径的任何部分,所以不必担心有人在其中滑过 \..\..而不应该去的地方。一个不好的例子是有人通过上传名为横向目录的文件来覆盖 .htpassword文件。
具有更统一的外观链接,统一的尺寸,统一的
字符。


https://en.wikipedia.org/wiki/Directory_traversal_attack


保养。路径改变,服务器改变。您对系统进行更改的需求。如果您需要重定位这些文件,但是将它们的绝对完整路径存储在数据库中,则可以将所有内容与 symlinks粘合在一起或更新所有记录。


这有一些例外。如果要将它们存储在每月文件夹中或按用户名存储。您可以将路径的该部分保存在单独的字段中。但是即使在那种情况下,您也可以基于记录中保存的数据动态地构建它。我发现最好保存尽可能少的路径信息。它们会生成一个配置或一个常量,您可以在将路径放置到文件所需的所有位置中使用。

pathlink也非常不同,因此通过仅保存名称,您可以从任何PHP页面链接它,而不必从路径中减去数据。我一直发现添加到文件名然后从路径中减去会更容易。

数据库(只是一些建议,用法可能有所不同)
像往常一样,用数据问自己,谁,什么,在哪里,何时


id- int主键自动递增
user_id- int外键,谁上传了它
哈希- char[40] *sha1*, unique什么哈希
hashname- varchar {timestampl}-{hash}。{ext},其中硬盘上的文件名
filename- varchar用户提供的原始名称,这样我们就可以向他们显示他们期望的名称(如果很重要)
状态-文件的 enum[public,private,deleted,pending.. etc]状态,取决于您的用例,您可能必须查看文件,或者某些文件是私有的,只有用户可以看到它们,某些文件是公开的,等等。
status_date- timestamp|datetime状态更改的时间。
create_date- timestamp|datetime创建文件的时间时,首选时间戳记,因为它使某些事情变得更容易,但在这种情况下,它应与哈希名使用相同的时间戳记。
type- varchar-mime type,在下载等时可用于设置mime类型。


如果希望不同的用户上传相同的文件,并且使用 file_hash,则可以使 hash字段成为 user_idhash的组合唯一索引,这样,只有在同一用户上传的情况下,它才会冲突相同的文件。您还可以根据需要根据时间戳和哈希值进行操作。

这是我能想到的基本内容,这并不是绝对的,只是我认为有用的某些领域。

单独拥有哈希值非常有用,如果您自己存储哈希值,则可以将其存储在sha1的 CHAR(40)中(占用的数据库空间少于 VARCHAR)并将排序规则设置为 UTF8_bin是二进制的。这使得对它的搜索区分大小写。尽管散列冲突的可能性很小,但这会增加一点保护,因为散列是大写小写字母。

如果您存储扩展名和时间戳,则始终可以随时构建 hashname。如果您发现自己一次又一次地创建事物,则可能只想将其存储在数据库中以简化PHP中的工作。

我喜欢将哈希放在链接中,没有扩展名,所以我的链接看起来像这样。

http://www.example.com/download/ad87109bfff0765f4dd8cf4943b04d16a4070fea


真正简单,真正通用,网址中的安全性始终相同大小等。

该“文件”的 hashname就像这样

1511848005-ad87109bfff0765f4dd8cf4943b04d16a4070fea.jpg


如果确实与相同的文件和不同的用户(我在上面提到)有冲突。您始终可以将时间戳记部分或user_id或两者都添加到链接中。如果您使用user_id,将其用零填充可能会很有用。例如,某些用户可能具有 ID:1,而某些用户可能是 ID:234,因此您可以将其保留到4个位置,并将其设置为 00010234。然后将其添加到哈希中,这几乎是不明显的:

1511848005-ad87109bfff0765f4dd8cf4943b04d16a4070fea0234.jpg


这里重要的是,因为 sha1始终为 40,并且id始终为 4,所以我们可以准确而轻松地将两者分开。这样,您仍然可以唯一地查找它。有很多不同的选择,但是很大程度上取决于您的需求。

访问
如下载。您应该始终使用PHP输出文件,不要让他们直接访问该文件。最好的方法是将文件存储在webroot之外( public_htmlwww文件夹上方)。然后,在PHP中,您可以将标头设置为正确的类型,并且基本上可以读出文件。除视频外,这几乎适用于所有其他功能。我不处理视频,所以这不是我的经验范围。但我发现最好将其视为所有文件数据都是文本,其标题会将文本变成图像,或者是excel文件或pdf。

不让他们直接访问文件的最大好处是,如果您有会员网站,或者不想在没有登录的情况下访问您的内容,则可以在向他们提供内容之前轻松地检查PHP是否已登录。而且,由于该文件位于webroot外部,因此他们无法以其他任何方式访问它。

最重要的是选择一致的东西,它仍然足够灵活,可以满足您的所有需求。

我确定我可以提出更多建议,但是如果您有任何建议,请随时发表评论。

基本流程


用户提交表单( enctype="multipart/form-data"


https://www.w3schools.com/tags/att_form_enctype.asp


服务器从Super Globals $_POST$_FILES表单接收帖子


http://php.net/manual/en/reserved.variables.files.php

$_FILES = [
'fieldname' => [
'name' => "MyFile.txt" // (comes from the browser, so treat as tainted)
'type' => "text/plain" // (not sure where it gets this from - assume the browser, so treat as tainted)
'tmp_name' => "/tmp/php/php1h4j1o" // (could be anywhere on your system, depending on your config settings, but the user has no control, so this isn't tainted)
'error' => "0" //UPLOAD_ERR_OK (= 0)
'size' => "123" // (the size in bytes)
]
];



检查错误 if(!$_FILES['fielname']['error'])
清除显示名称 $filename = htmlentities($str, ENT_NOQUOTES, "UTF-8");
保存文件,创建数据库记录(PSUDO-CODE)


像这样:

 $path = __DIR__.'/uploads/'; //for exmaple

$time = time();
$hash = hash_file('sha1',$_FILES['fielname']['tmp_name']);
$type = $_FILES['fielname']['type'];
$hashname = $time.'-'.$hash.strrchr($_FILES['fielname']['name'], '.');
$status = 'pending';

if(!move_uploaded_file ($_FILES['fielname']['tmp_name'], $path.$hashname )){
//failed
//do somehing for errors.
die();
}


//store record in db


http://php.net/manual/en/function.move-uploaded-file.php


创建链接(因路由而异),简单的方法是像 http://www.example.com/download?file={$hash}这样创建链接,但 http://www.example.com/download/{$hash}较难看
用户点击链接进入下载页面。


获取输入并查找记录

$hash = $_GET['file'];

$stmt = $PDO->prepare("SELECT * FROM attachments WHERE hash = :hash LIMIT 1");
$stmt->execute([":hash" => $hash]);

$row = $stmt->fetch(PDO::FETCH_ASSOC);

print_r($row);


http://php.net/manual/en/intro.pdo.php

等等....

干杯!

关于php - PHP如何将文件服务器中的文件链接到数据库中的信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47523599/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com