添加注释

用户贡献的注释 20 个注释

olszewski_marek at yahoo dot com
23 年前
以下是一个简单的控制谁下载您的文件的方法...

您需要设置:$filename、$downloaddir、$safedir 和 $downloadURL。

基本上,$filename 是文件名称,$downloaddir 是服务器上的任何目录,$safedir 是浏览器无法访问的目录,其中包含名为 $filename 的文件,而 $downloadURL 是 $downloaddir 的 URL 等效项。

此方法的工作原理是,当用户想要下载文件时,会在 $downloaddir 中创建一个随机命名的目录,并创建一个指向所请求文件的符号链接。然后将浏览器重定向到新链接,并开始下载。

该代码还会在为自己创建符号链接之前删除任何以前的用户创建的符号链接。这样实际上每次只保留一个符号链接,并防止以前的用户在不通过此脚本的情况下再次下载文件。如果在另一个人从该链接下载时删除符号链接,似乎没有问题。

如果下载文件的人不多,此方法不太好,因为符号链接将不会被删除,直到另一个人下载相同的文件。

无论如何,希望您喜欢

<?php
$letters
= 'abcdefghijklmnopqrstuvwxyz';
srand((double) microtime() * 1000000);
$string = '';
for (
$i = 1; $i <= rand(4,12); $i++) {
$q = rand(1,24);
$string = $string . $letters[$q];
}
$handle = opendir($downloaddir);
while (
$dir = readdir($handle)) {
if (
is_dir($downloaddir . $dir)){
if (
$dir != "." && $dir != ".."){
@
unlink($downloaddir . $dir . "/" . $filename);
@
rmdir($downloaddir . $dir);
}
}
}
closedir($handle);
mkdir($downloaddir . $string, 0777);
symlink($safedir . $filename, $downloaddir . $string . "/" . $filename);
Header("Location: " . $downloadURL . $string . "/" . $filename);
?>
Wixiweb
6 年前
如果您使用 suhosin 扩展,则必须使用以下命令允许 symlink
> suhosin.executor.allow_symlink = On

检查您的 /var/log/syslog 文件以获取更多信息
> suhosin: ALERT - symlink called during open_basedir
reddy1042001 at yahoo dot co dot in
14 年前
Windows 上的符号链接由 Symlink() 创建,它只接受绝对路径,而不是相对路径。Windows 上的相对路径不支持符号链接。
Anonymous
17 年前
嗯,废话... 我对以前的笔记只有这句话要说。请删除它。:)

Windows Vista 现在有了自己的符号链接程序(mklink)。希望未来版本的 Windows 版 PHP 会添加此功能?

无论如何,这在 Vista 上将起作用(假设您的 PHP 用户具有适当的权限)
<?php
define
('SYMLINK_FILE', 0);
define('SYMLINK_DIR', 1);
define('SYMLINK_JUNCTION', 2);
function
symlink ($target, $link, $flag = SYMLINK_FILE) {
switch (
$flag) {
case
SYMLINK_DIR: $pswitch = '/d'; break;
case
SYMLINK_JUNCTION: $pswitch = '/j'; break;
case
SYMLINK_FILE:
default:
$pswitch = ''; break;
}
// Change / to \ because it will break otherwise.
$target = str_replace('/', '\\', $target);
$link = str_replace('/', '\\', $link);
return
exec('mklink ' . $pswitch . ' "' . $link . '" "' . $target . '"');
}
?>
Numien
17 年前
使用符号链接进行受控文件访问与使用 readfile() 的唯一区别在于 HTTP 服务器将自动处理符号链接的 content-type。

如果你始终希望下载文件,这可能是一个负面因素。但是,如果你希望在浏览器中查看非预定义类型的文件,这将是一个真正的优势。

当然,你可以使用 fileinfo/mime-magic 来实现这一点,但它们需要一个模块,而该模块并不总是可以在共享主机上使用。
zeomniscient
10 年前
背景:Windows 操作系统上的 PHP CLI。

不要忘记以“以管理员身份运行”启动控制台,否则符号链接将返回“false”并引发以下错误
警告:symlink(): 无法创建符号链接,错误代码 (1314)
flobee
9 年前
我喜欢做 sym/hard linking,但当思考错误时,它并不那么简单 :-)
手册页说:目标是 _linkname_,从该点开始创建成功的相对链接是从应创建链接的目录开始,例如
/myfiles/now/here/
/myfiles/links/

chdir( realpath(dirname($target)));
你需要创建/找出源的相对路径,否则链接中将使用绝对路径。

如果你从源开始创建目标路径,例如
"/myfiles/now/here/../../later/" 并且链接应该指向 /myfiles/later/,你需要使用 realpath( dirname() ) 设置新的位置,使用 chdir(),并从此处开始链接到源,即 ../now/here/
你可以在以下情况下找出这一点,例如:当拥有源和目标的绝对路径时
$dirTo = realpath(dirname($to));
chdir($dirTo);
$linkName = basename($to);
$target = $dirTo . DIRECTORY_SEPARATOR . $linkName;
$srcFile = getRelativeDirectory($from, $to); //基本上是一个查找 from -> to 的函数,但在这种情况下,from 是你需要开始的目标。
以下是一些示例,说明如何将路径分割成块以查找相对路径
alvaro at demogracia dot com
6 年前
要删除符号链接,你需要使用

- rmdir() 在 Windows 上
- unlink() 在其他地方

<?php
function removeSymlink($path) {
if (
PHP_SHLIB_SUFFIX==='dll') {
return
rmdir($path);
}
return
unlink($path);
}
raat1979 at gmail dot com
9 年前
请注意,至少在 Windows 2008 R2 上的 PHP 5.3 中,symlink 函数受 statcache 影响。

我遇到了错误 183,表明链接存在。虽然符号链接实际上已被另一个进程移到了不同的位置,并且肯定不再存在。
使用文件名调用 clearstatcache 不会起作用。很可能因为文件名被转换为设备路径(例如 "\Device\HarddiskVolume1\D-Drive\www\pp\#static\index.html"),这是 Windows 调用的要求。

最简单的方法是直接调用 clearstatcache,不带文件名来解决问题。

如果你真的想使用文件名调用 clearstatcache,你可以对已删除的符号链接(仍然存在于 statcache 中)使用 readlink 来获取文件名。
例如,类似于以下代码
<?php
if(@symlink('d:/www/pp/#static/index.html','d:/www/index.html')===false){
//链接失败,可能是 statcache 问题?我们尝试获取目标,如果它是 statcache 问题,这应该可以正常工作

if(($rl = @readlink($target))===false) return false; //不是缓存问题,因为对不存在文件的 stat 失败,一定是其他问题...

//清除实际目标的 stat 缓存,奇怪的是,即使这是目标而不是要创建的符号链接,这也起作用了 (*)
clearstatcache(true,$rl);

if(@
symlink($source,$target) ===false) return false; //无法创建符号链接
?>

*对于 Windows 上的 PHP 来说,看起来 statcache 是维护在目标上,而不是实际的符号链接上(这将简化获取文件属性并限制 statcache 的大小)
Anonymous
17 年前
<?

/**
* 在 Windows 上模拟符号链接的函数。
* 使用 junction 实用程序,可从以下网站获得
* http://www.sysinternals.com
* 请注意,这仅在 NTFS 卷上有效。
*
* junction 实用程序的语法为
* junction <junction directory> <junction target>
*
* 请注意,Junction 命令的参数顺序
* 与 symlink 函数相反!
*
* @param string $target
* @param string $link
*/
function _symlink( $target, $link ) {
if ($_SERVER['WINDIR'] || $_SERVER['windir']) {
exec('junction "' . $link . '" "' . $target . '"');
} else {
symlink($target,$link);
}
}

function _unlink($link ) {
if ($_SERVER['WINDIR'] || $_SERVER['windir']) {
exec('junction -d "' . $link . '"');
} else {
unlink($link);
}
}
?>
anything at the domain williamfrantz.com
18 年前
Olszewski_marek 提出了一个很好的建议,但 readfile() 函数也可以用来隐藏最终用户的文件下载。

/* 设置要发送的文件 */
$downloadDir = "some/secret/directory/";
$file = "theFileName.dat";

/* IE 必须使用,否则 Content-disposition 将被忽略 */
if(ini_get('zlib.output_compression')) ini_set('zlib.output_compression', 'Off');

/* 输出强制“另存为”对话框的 HTTP 头 */
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\\"$file\\";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".@filesize($downloadDir.$file));

/* 阻止脚本在处理大文件时超时 */
set_time_limit(0);

/* 使用 @ 发送整个文件以忽略所有错误 */
@readfile($downloadDir.$file);

/* 立即退出,以防止垃圾信息跟随文件内容 */
exit;
Calin
12 年前
在 IIS(Internet Information Services)上,你需要设置权限以允许创建符号链接。

转到本地安全策略 -> 本地策略 -> 用户权限分配,右键单击创建符号链接 -> 属性 -> 添加用户或组,并添加“IUSR”用户,该用户应该是与 IIS 关联的用户。
可能需要重新启动。

如果这不起作用,请转到 IIS 管理器 -> 身份验证 -> 选择匿名身份验证 -> 编辑,并输入你当前登录的用户,该用户应该是管理员。
单击“确定”,现在 PHP 中的 symlink() 函数应该可以正常工作。
php-user at protonmail dot com
1 年前
没有记录的一点是,此函数会检查目标文件是否存在。这种行为可能非常不方便,如果你想要创建多个指向本地挂载的远程文件的符号链接,例如使用 Rclone。在这种特定情况下,此函数可能需要 2 秒甚至更长时间才能完成。
Scare!
1 年前
在 Windows 上,symlink() 无法接受包含符号链接的路径。首先使用 realpath() https://php.net/manual/en/function.realpath.php 展开路径。
lingtalfi
9 年前
如果 symlink 似乎无法正常工作,请尝试将目标参数定义为绝对路径。
在 MacOsX PHP5.5 上进行编码时,我注意到,在某些情况下,使用目标参数的绝对路径是我唯一能够创建正确符号链接的方法。
ewering at gmail dot com
16 年前
此函数有时会莫名其妙地无法正常工作,返回 FALSE 并且不创建符号链接。使用 exec('ln -s source dest') 执行相同操作会完美地工作。我建议使用后者。
contact at tcknetwork dot com
18 年前
为了使你的代码在 unix 和 win32 上可移植,请执行以下操作
1. 下载 http://www.dynawell.com/reskit/microsoft/win2000/linkd.zip
2. 解压缩,将 linkd.exe 放入 C:\Windows\System32 或 C:\WINNT\System32
3. 在您的代码中包含以下内容
<?
函数 _syslink($t /*目标*/ ,$l /*链接*/ ) {
如果 ($_SERVER["WINDIR"]) {
$p=dirname($_SERVER["SCRIPT_FILENAME"])."/";
exec("linkd ".$p.$t." ".$p.$l);
} 否则 syslink($t,$l);
}
函数 _unlink($l /*链接*/ ) {
如果 ($_SERVER["WINDIR"]) {
$p=dirname($_SERVER["SCRIPT_FILENAME"])."/";
exec("linkd ".$p.$l." /D");
} 否则 unlink($l);
}
?>
4. 尽情享受
_symlink(TARGET,LINK) 在 *nix 上的工作方式类似于 symlink()
_unlink(LINK) 用于正确删除创建的链接
匿名
18 年前
Olszewski 的方法似乎很不错,但是为了稍微提高一下安全性,他的脚本的第五行应该写成
<?
...
$q = rand(1,26);
...
?>

而不是 rand(1,24).
Porjo
14 年前
请记住,当使用 NFS 等共享文件系统时,您可能不希望使用绝对路径创建符号链接,例如

在服务器 1 上,您正在运行一个 PHP 脚本,该脚本需要创建一个名为 widget2 的符号链接,该链接指向 NFS 共享中名为 widget1 的文件,该共享挂载在您的本地主机上的 /mnt/nfs/widgets

在服务器 2 上,同一个 NFS 共享挂载在 /usr/local/widgets 下

如果您在服务器 1 上使用绝对路径,那么服务器 2 将尝试引用 /mnt/nfs/widgets/widget1,而它将无法找到...

您需要先 cd 到目录中,然后创建链接 - 这样链接将是相对的。除非您从将创建符号链接的同一目录运行 PHP 脚本,否则您无法使用 symlink()。请改用以下方式使用 exec()

<?php

exec
("cd <nfs 挂载路径>; ln -s <目标> <链接名称>");

?>
aircha at cix dot co dot uk
19 年前
Olszewski 的动态创建可下载链接的方法相当不错。

我在 Apache 下使用另一种技术,如果要获取文件,可以使用类似于以下的 URL

mydomain.com/files/mysecretfile.doc

但实际上 Apache 将其重定向到一个带有类似以下 URL 的脚本

mydomain.com/utilities/downloadfile.php?filename=mysecretfile.doc

(浏览器地址栏仍将显示第一个 URL)。

然后,脚本 downloadfile.php 可以处理所有棘手的操作,例如检查会话变量以查看是否有人登录,他们是否有权访问 mysecretfile.doc,以及是否需要在下载之前进行加密。

这样做的好处是,实现与 Olszewski 相同功能的 PHP 代码更短,因此执行速度可能更快。但更重要的是,一个非专业的黑客可能认为他所要做的就是找到 /home/user/public_html/files/mysecretfile.doc 下的 myverysecurefile.doc,或者复制 URL - 但是那里什么都没有!他找不到它或不会得到 Apache 错误页面。
To Top