'bad params']); if (strpos($f, '..') !== false) json_out(400, ['error' => 'bad path']); $sig = substr(hash_hmac('sha256', $f . '|' . $e, $SECRET), 0, 16); if (!hash_equals($sig, $t) || time() > $e) json_out(403, ['error' => 'invalid or expired token']); $root = realpath(__DIR__ . '/..'); if ($PRIVATE_DIR !== '') { // 私有目录优先(嵌入链接写纯文件名即可);目录不存在时退回站内路径, // 让留在 web 目录里的样例图纸按原路径继续可用(这些文件本来就允许直链, // 退回不新增暴露面)。要保护的图纸必须移出 web 目录放进私有目录。 $full = realpath($PRIVATE_DIR . '/' . basename($f)); $ok = $full && strpos($full, realpath($PRIVATE_DIR)) === 0 && is_file($full); if (!$ok) { $full = realpath($root . '/' . $f); $ok = $full && strpos($full, $root) === 0 && is_file($full); } } else { $full = realpath($root . '/' . $f); $ok = $full && strpos($full, $root) === 0 && is_file($full); } if (!$ok) json_out(404, ['error' => 'not found']); $data = file_get_contents($full); $origName = basename($f); if (preg_match('/\.enc$/i', $f)) { $nonce = substr($data, 0, 16); $key = hash('sha256', $SECRET . $nonce, true); $body = substr($data, 16); $out = ''; for ($i = 0; $i < strlen($body); $i++) { $out .= $body[$i] ^ $key[$i % strlen($key)]; } // 加密体头部藏着原文件名(落盘名是随机的,链接里看不出是哪张图) if (strlen($out) > 2) { $nl = unpack('n', substr($out, 0, 2))[1]; if ($nl > 0 && $nl <= 255 && strlen($out) > 2 + $nl) { $origName = substr($out, 2, $nl); $out = substr($out, 2 + $nl); } } $data = $out; } header('X-Filename: ' . rawurlencode($origName)); header('Access-Control-Expose-Headers: X-Filename'); // 上传时已经 gzip 过,解密后就是 gzip 流,直接标 Content-Encoding 让浏览器解; // 明文文件(如 dxf)在线压一次,DXF 文本能压到 1/8 左右 $send = $data; if (substr($send, 0, 2) === "\x1f\x8b") { header('Content-Encoding: gzip'); } elseif (!ini_get('zlib.output_compression') && strlen($data) > 1024) { $gz = gzencode($data, 6); if ($gz !== false) { $send = $gz; header('Content-Encoding: gzip'); } } header('Content-Type: application/octet-stream'); header('Content-Length: ' . strlen($send)); header('Cache-Control: no-store'); header('Content-Disposition: inline'); echo $send;