简体   繁体   English

PHP - 如何在Content-Disposition中设置完整目录路径?

[英]PHP - How to set full directory path in Content-Disposition?

I am passing a filename to a download page. 我将文件名传递给下载页面。
ie somefile.xls 即somefile.xls

The download page adds back in the full directory path onto the filename. 下载页面将完整目录路径添加回文件名。
ie c:\\temp\\somefile.xls 即c:\\ temp \\ somefile.xls

The problem is that now setting the 'Content-Disposition' of the header doesn't work. 问题是现在设置标题的“Content-Disposition”不起作用。 The filename it wants to download is the full directory-filename path. 它要下载的文件名是完整的directory-filename路径。 ie c_temp_somefile 即c_temp_somefile

Can the Content-Disposition handle a full path? Content-Disposition可以处理完整路径吗?

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

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标头中放置几乎所有Content-Disposition但出于安全原因,大多数浏览器将忽略或替换路径并将其转换为运行它们的操作系统的有效文件名。

Content-Disposition is only a hint to the browser, it is not mandatory for the web client to respect this setting. Content-Disposition只是浏览器的提示,Web客户端不一定要尊重此设置。

So, no, you can't force the download to a specific directory on the client computer. 所以,不,你不能强制下载到客户端计算机上的特定目录。

Don't pass the full path via the header string, but use the base name ( $myad ) instead. 不要通过标题字符串传递完整路径,而是使用基本名称( $myad )。

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). 您应该对$_GET['myad']使用更好的验证,因为您的脚本会将任意路径传递给用户( readfile()获取未过滤的用户输入)。 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. 使用realpath计算实际路径,确保文件在允许的文件夹中,然后在完整路径上使用basename()来获取纯文件名。 Pass this substring via the Content-Disposition header, but use the real path for readfile() . 通过Content-Disposition标头传递此子字符串,但使用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. 如果$_GET['myad']包含../../../some/full/path ,您的脚本会很乐意将任何请求的可读文件发送给客户端。

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);
}

Never ever. 永远不能。 If a browser accepts full paths it is time to file a bug, quickly: this would be a major security hole. 如果浏览器接受完整路径,则应该快速提交错误:这将是一个主要的安全漏洞。

我不知道这是否会有所帮助,但我认为excel文档的内容类型标题可能不是真的正确,我自己没有尝试过,但那些微软软件包都是满口的,就像mirosoft这个词一样
application/vnd.openxmlformats-officedocument.wordprocessingml.document

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM