PHP - 如何在内容处置中设置完整目录路径?

发布于 2024-08-11 21:10:37 字数 926 浏览 13 评论 0原文

我正在将文件名传递到下载页面。
ie somefile.xls

下载页面将完整目录路径添加回文件名中。
ie c:\temp\somefile.xls

问题是现在设置标头的“Content-Disposition”不起作用。它要下载的文件名是完整的目录文件名路径。 ie c_temp_somefile

Content-Disposition 可以处理完整路径吗?

如果可以,我如何让我的脚本正确下载文件?

代码是:

$myad = $_GET['myad'];
$glob_string =  realpath('/foldera/folderb/folderc'). DIRECTORY_SEPARATOR .$myad;

header('Content-Type: application/excel');
$headerstring = 'Content-Disposition: attachment; filename='.$glob_string;
header($headerstring);
readfile($myad);

更新代码(来自答案):

$myad = $_GET['myad'];
$glob_string =  realpath('/mit/mit_tm/mrl_bol'). DIRECTORY_SEPARATOR .$myad;

header('Content-Type: application/excel');
$headerstring = 'Content-Disposition: attachment; filename='.$myad;
header($headerstring);
readfile($glob_string);    

I am passing a filename to a download page.
ie somefile.xls

The download page adds back in the full directory path onto the filename.
ie c:\temp\somefile.xls

The problem is that now setting the 'Content-Disposition' of the header doesn't work. The filename it wants to download is the full directory-filename path.
ie c_temp_somefile

Can the Content-Disposition handle a full path?

If it can how do I get my script to properly download the file?

Code is:

$myad = $_GET['myad'];
$glob_string =  realpath('/foldera/folderb/folderc'). DIRECTORY_SEPARATOR .$myad;

header('Content-Type: application/excel');
$headerstring = 'Content-Disposition: attachment; filename='.$glob_string;
header($headerstring);
readfile($myad);

UPDATED code (from answers):

$myad = $_GET['myad'];
$glob_string =  realpath('/mit/mit_tm/mrl_bol'). DIRECTORY_SEPARATOR .$myad;

header('Content-Type: application/excel');
$headerstring = 'Content-Disposition: attachment; filename='.$myad;
header($headerstring);
readfile($glob_string);    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

若有似无的小暗淡 2024-08-18 21:10:37

不要通过标头字符串传递完整路径,而是使用基本名称 ($myad)。

您确实应该对 $_GET['myad'] 使用更好的验证,因为您的脚本会将任意路径传递给用户(readfile() 获取未经过滤的用户输入) 。这是一个安全漏洞!

使用realpath计算真实路径,确保文件位于允许的文件夹内,然后在完整路径上使用basename()来获取纯文件名。通过 Content-Disposition 标头传递此子字符串,但使用 readfile() 的真实路径。


更新:您更新的代码仍然包含安全漏洞。如果 $_GET['myad'] 包含 ../../../some/full/path,您的脚本会很乐意将任何请求的可读文件发送到客户端。

您应该使用类似于以下代码片段的内容:

$myad = $_GET['myad'];

$rootDir = realpath('/mit/mit_tm/mrl_bol');
$fullPath = realpath($rootDir . '/' . $myad);

// Note that, on UNIX systems, realpath() will return false if a path
// does not exist, but an absolute non-existing path on Windows.
if ($fullPath && is_readable($fullPath) && dirname($fullPath) === $rootDir) {
    // OK, the requested file exists and is in the allowed root directory.
    header('Content-Type: application/excel');
    // basename() returns just the file name.
    header('Content-Disposition: attachment; filename=' . basename($fullPath));
    readfile($fullPath);
}

Don't pass the full path via the header string, but use the base name ($myad) instead.

You should really use a better validation for $_GET['myad'], since your script will pass arbitrary paths to the user (readfile() gets the unfiltered user input). This is a security hole!

Calculate the real path using realpath, make sure that the file is within a allowed folder, then use basename() on the full path to get the plain file name. Pass this substring via the Content-Disposition header, but use the real path for readfile().


UPDATE: Your updated code still contains a security hole. If $_GET['myad'] contained ../../../some/full/path, your script would happily send any requested readable file to the client.

You should use something along the lines of the following snippet:

$myad = $_GET['myad'];

$rootDir = realpath('/mit/mit_tm/mrl_bol');
$fullPath = realpath($rootDir . '/' . $myad);

// Note that, on UNIX systems, realpath() will return false if a path
// does not exist, but an absolute non-existing path on Windows.
if ($fullPath && is_readable($fullPath) && dirname($fullPath) === $rootDir) {
    // OK, the requested file exists and is in the allowed root directory.
    header('Content-Type: application/excel');
    // basename() returns just the file name.
    header('Content-Disposition: attachment; filename=' . basename($fullPath));
    readfile($fullPath);
}
甜尕妞 2024-08-18 21:10:37

您可以将几乎所有内容放入 Content-Disposition 标头中,但出于安全原因,大多数浏览器会忽略或替换路径,并将它们转换为适用于其运行的操作系统的有效文件名。

Content-Disposition 只是对浏览器的提示,Web 客户端并不强制遵守此设置。

因此,不,您不能强制下载到客户端计算机上的特定目录。

You can put almost everything you want in the Content-Disposition header but most browsers, for security reasons, will ignore or replace paths and convert them to a valid filename for the operating system they're running on.

Content-Disposition is only a hint to the browser, it is not mandatory for the web client to respect this setting.

So, no, you can't force the download to a specific directory on the client computer.

风轻花落早 2024-08-18 21:10:37

从来没有。如果浏览器接受完整路径,那么就需要快速提交错误:这将是一个主要的安全漏洞。

Never ever. If a browser accepts full paths it is time to file a bug, quickly: this would be a major security hole.

明明#如月 2024-08-18 21:10:37

我不知道这是否有帮助,但我认为excel文档的内容类型标头可能不太正确,我自己没有尝试过,但是那些微软的软件包满嘴都是,比如mirosoft word是
<代码>application/vnd.openxmlformats-officedocument.wordprocessingml.document

I dont know if this would help, but I think that the content-type header for excel document might not be really correct, I have not tried it myself, but those microsoft packages come in a mouthfull, like mirosoft word is
application/vnd.openxmlformats-officedocument.wordprocessingml.document

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文