Files

59 lines
1.9 KiB
PHP
Raw Permalink Normal View History

2026-10-09 22:49:53 +07:00
<?php
declare(strict_types=1);
const WEB_MEDIA_ROOT = '/opt/im-server/media';
function failDownload(int $status, string $message): never
{
http_response_code($status);
header('Content-Type: text/plain; charset=utf-8');
echo $message;
exit;
}
function safeDownloadName(string $fileName, string $fallback): string
{
$name = basename(str_replace('\\', '/', $fileName));
$name = preg_replace('/[^\p{L}\p{N}._ -]+/u', '_', $name) ?: '';
$name = trim($name, " .\t\n\r\0\x0B");
if ($name === '') {
$name = $fallback;
}
return mb_substr($name, 0, 180, 'UTF-8');
}
$url = trim((string)($_GET['url'] ?? ''));
$requestedName = trim((string)($_GET['name'] ?? ''));
if ($url === '') {
failDownload(400, '缺少媒体地址');
}
$path = (string)(parse_url($url, PHP_URL_PATH) ?: $url);
$path = rawurldecode($path);
if (!preg_match('#^/fs/[0-9]+/[A-Za-z0-9_./ -]+$#', $path) || str_contains($path, '..')) {
failDownload(400, '媒体地址不合法');
}
$root = realpath(WEB_MEDIA_ROOT);
$fullPath = realpath(rtrim(WEB_MEDIA_ROOT, '/') . $path);
if ($root === false || $fullPath === false || !str_starts_with($fullPath, $root . DIRECTORY_SEPARATOR) || !is_file($fullPath)) {
failDownload(404, '媒体文件不存在');
}
$fallbackName = basename($fullPath);
$downloadName = safeDownloadName($requestedName, $fallbackName);
if (!pathinfo($downloadName, PATHINFO_EXTENSION)) {
$downloadName .= '.' . (pathinfo($fallbackName, PATHINFO_EXTENSION) ?: 'jpg');
}
$mime = mime_content_type($fullPath) ?: 'application/octet-stream';
header('Content-Type: ' . $mime);
header('Content-Length: ' . (string)filesize($fullPath));
header(
'Content-Disposition: attachment; filename="' . addcslashes($downloadName, "\\\"") . '"; filename*=UTF-8\'\''
. rawurlencode($downloadName)
);
header('Cache-Control: no-store');
readfile($fullPath);