PHP 会议日本 2024
添加注释

用户贡献的注释 19 条注释

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

您需要设置:$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);
?>
4
Wixiweb
6 年前
如果您使用 suhosin 扩展,则必须使用以下命令允许符号链接
> suhosin.executor.allow_symlink = On

检查您的 /var/log/syslog 文件以获取更多信息
> suhosin: ALERT - symlink called during open_basedir
10
reddy1042001 at yahoo dot co dot in
14 年前
Windows 上的符号链接由 Symlink() 创建,它只接受绝对路径,而不接受相对路径。Windows 上不支持符号链接的相对路径。
4
匿名
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;
}
// 将 / 替换为 \,否则会出错
$target = str_replace('/', '\\', $target);
$link = str_replace('/', '\\', $link);
return
exec('mklink ' . $pswitch . ' "' . $link . '" "' . $target . '"');
}
?>
2
Numien
17 年前
使用符号链接进行受控文件访问与使用 readfile() 的唯一区别在于 HTTP 服务器会自动处理符号链接的内容类型。

如果您始终希望将其下载,这可能是一个缺点。但是,如果您希望浏览器能够查看非预定义类型的文件,这将是一项真正的优势。

当然,您可以使用 fileinfo/mime-magic 来做到这一点,但这些都需要一个模块,而该模块在共享主机上并不总是可用。
5
zeomniscient
10 年前
上下文:Windows 操作系统上的 php cli。

不要忘记以“以管理员身份运行”启动控制台,否则 symlink 将返回“false”并引发以下错误
警告:symlink(): 无法创建符号链接,错误代码(1314)
2
flobee
9 年前
sym/硬链接我喜欢相对地做很多,但在错误地思考时并不那么简单 :-)
手册页说:目标是_链接名_,从该点开始成功创建相对链接是从应该创建链接的目录开始,例如
/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 是您需要从中开始的目标。
下面您可以找到一些有关如何将路径拆分为块以查找相对路径的示例
2
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;
1
alvaro at demogracia dot com
6 年前
要删除符号链接,您需要使用

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

<?php
function removeSymlink($path) {
if (
PHP_SHLIB_SUFFIX==='dll') {
return
rmdir($path);
}
return
unlink($path);
}
1
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,则可以使用已删除的符号链接上的 readlink(该链接仍保留在 statcache 中)来获取文件名。
例如,如下所示
<?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 的大小)
1
Anonymous
18 年前
<?

/**
* 一个在 Windows 上模拟符号链接的函数。
* 使用可从以下位置获得的连接实用程序
* http://www.sysinternals.com
* 请注意,这仅在 NTFS 卷上有效。
*
* 连接实用程序的语法为
* 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);
}
}
?>
1
Calin
12 年前
在 IIS(Internet Information Services)上,您需要设置权限以允许创建符号链接。

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

如果这不起作用,请转到 IIS 管理器 -> 身份验证 -> 选择匿名身份验证 -> 编辑并输入您当前登录的用户,该用户应为管理员。
单击确定,现在 php 中的 symlink() 函数应该可以正常工作了。
0
php-user at protonmail dot com
1 年前
未记录的一件事是此函数会检查目标文件是否存在。如果您想创建多个指向本地挂载的远程文件的符号链接(例如使用 Rclone),这种行为可能会非常不方便。在这种特定情况下,此函数可能需要 2 秒甚至更长时间才能完成。
0
Scare!
2 年前
在 Windows 上,symlink() 不接受包含符号链接的路径。首先使用 realpath() https://php.net/manual/en/function.realpath.php 展开路径。
0
lingtalfi
10 年前
如果 symlink 似乎无法正常工作,请尝试将 target 参数定义为绝对路径。
在 MacOsX PHP5.5 上编码时,我注意到在某些情况下,在 target 参数上使用绝对路径是我能够创建正确符号链接的唯一方法。
0
ewering at gmail dot com
17 年前
这个函数有时会莫名其妙地无法工作,返回 FALSE 并且没有创建符号链接。使用 exec('ln -s source dest') 可以完美地解决这个问题。我建议使用后者。
-2
Porjo
15年前
请记住,当使用共享文件系统(例如 NFS)时,您可能不希望使用绝对路径创建符号链接,例如:

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

在 Server2 上,同一个 NFS 共享挂载在 /usr/local/widgets 下。

如果您在 Server1 上使用绝对路径,那么 Server2 将尝试引用 /mnt/nfs/widgets/widget1,但它将无法找到……

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

<?php

exec
("cd <nfs mount path>; ln -s <target> <link_name>");

?>
-2
contact at tcknetwork dot com
19年前
要使您的代码在 unix 和 win32 上可移植,请执行以下操作:
1. 下载 http://www.dynawell.com/reskit/microsoft/win2000/linkd.zip
2. 解压缩,将 linkd.exe 放入 C:\Windows\System32 或 C:\WINNT\System32
3. 在您的代码中包含以下内容:
<?
function _syslink($t /*target*/ ,$l /*link*/ ) {
if ($_SERVER["WINDIR"]) {
$p=dirname($_SERVER["SCRIPT_FILENAME"])."/";
exec("linkd ".$p.$t." ".$p.$l);
} else syslink($t,$l);
}
function _unlink($l /*link*/ ) {
if ($_SERVER["WINDIR"]) {
$p=dirname($_SERVER["SCRIPT_FILENAME"])."/";
exec("linkd ".$p.$l." /D");
} else unlink($l);
}
?>
4. 尽情享受
_symlink(TARGET,LINK) 的工作方式与 *nix 上的 symlink() 相同
_unlink(LINK) 正确删除创建的链接
-2
Anonymous
18 年前
Olszewski 的脚本看起来不错,但为了提高安全性,他的脚本的第五行应该写成
<?
...
$q = rand(1,26);
...
?>

而不是 rand(1,24)。
To Top