<?php
if (!array_key_exists("i", $_GET) || !is_numeric($_GET["i"]))
die("索引未指定或非数字");
$index = (int) $_GET["i"];
$arch = RarArchive::open("example.rar");
if ($arch === FALSE)
die("无法打开 example.rar");
$entries = $arch->getEntries();
if ($entries === FALSE)
die("无法检索条目");
if (!array_key_exists($index, $entries))
die("没有这样的索引: $index");
$orfilename = $entries[$index]->getName(); //UTF-8 编码
$filesize = $entries[$index]->getUnpackedSize();
/* 你可以在这里检查 HTTP_IF_MODIFIED_SINCE 并与
* $entries[$index]->getFileTime() 进行比较。 你也可以发送一个
* "最后修改" 头 */
$fp = $entries[$index]->getStream();
if ($fp === FALSE)
die("无法打开存档中索引为 $index 的文件。");
$arch->close(); //不再需要;流是独立的
function detectUserAgent() {
if (!array_key_exists('HTTP_USER_AGENT', $_SERVER))
return "其他";
$uas = $_SERVER['HTTP_USER_AGENT'];
if (preg_match("@Opera/@", $uas))
return "Opera";
if (preg_match("@Firefox/@", $uas))
return "Firefox";
if (preg_match("@Chrome/@", $uas))
return "Chrome";
if (preg_match("@MSIE ([0-9.]+);@", $uas, $matches)) {
if (((float)$matches[1]) >= 7.0)
return "IE";
}
return "其他";
}
/*
* 我们有 3 个选项:
* - 对于支持 RFC 2231 的 FF 和 Opera,使用该格式。
* - 对于 IE 和 Chrome,使用 attwithfnrawpctenclong
* (http://greenbytes.de/tech/tc2231/#attwithfnrawpctenclong)
* - 对于其他浏览器,如果可能,转换为 ISO-8859-1
*/
$formatRFC2231 = 'Content-Disposition: attachment; filename*=UTF-8\'\'%s';
$formatDef = 'Content-Disposition: attachment; filename="%s"';
switch (detectUserAgent()) {
case "Opera":
case "Firefox":
$orfilename = rawurlencode($orfilename);
$format = $formatRFC2231;
break;
case "IE":
case "Chrome":
$orfilename = rawurlencode($orfilename);
$format = $formatDef;
break;
default:
if (function_exists('iconv'))
$orfilename =
@iconv("UTF-8", "ISO-8859-1//TRANSLIT", $orfilename);
$format = $formatDef;
}
header(sprintf($format, $orfilename));
//从此以后无法发送错误消息(头文件已发送)
//用真实的 content type 替换,也许从文件扩展名推断
$contentType = "application/octet-stream";
header("Content-Type: $contentType");
header("Content-Transfer-Encoding: binary");
header("Content-Length: $filesize");
if ($_SERVER['REQUEST_METHOD'] == "HEAD")
die();
while (!feof($fp)) {
$s = @fread($fp, 8192);
if ($s === false)
break; //发送错误消息毫无用处
echo $s;
}
?>