进行了一些优化

This commit is contained in:
2026-08-27 03:49:56 +08:00
parent 50c5769d01
commit f9e411dda8
+82 -56
View File
@@ -329,18 +329,21 @@ class Download {
$idx = (int) $row['source_index'];
if (empty($meta['downloads'][$idx]['url'])) $this->fail_410();
// HEAD probes validate the link but must never consume it.
$is_head = strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')) === 'HEAD';
// Probes (HEAD requests and Speculative-Loading prefetches) validate
// availability but must never consume a use nor waste bandwidth.
$is_probe = $this->is_probe_request();
$target_url = esc_url_raw((string) $meta['downloads'][$idx]['url']);
// Local attachment / uploads file: stream without artificial throttling.
$local_path = $this->resolve_local_download_path($target_url);
if ($local_path !== '' && is_readable($local_path)) {
$delivered = $this->stream_local_file($local_path);
// Count only fully delivered bodies; aborted transfers stay reusable.
if ($delivered && !$is_head) {
$this->consume_token($row, $token);
$this->send_download_headers($local_path);
if (!$is_probe) {
// Count only fully delivered bodies; aborted transfers stay reusable.
if ($this->stream_body($local_path)) {
$this->consume_token($row, $token);
}
}
exit;
}
@@ -348,13 +351,84 @@ class Download {
nocache_headers();
wp_redirect($target_url, 302);
// Remote hosts give no completion signal, so the redirect hand-off
// counts as delivery; HEAD probes still never consume.
if (!$is_head) {
// counts as delivery; probes still never consume.
if (!$is_probe) {
$this->consume_token($row, $token);
}
exit;
}
/**
* Requests that inspect the link instead of taking the download: plain
* HEAD plus browser speculative prefetches (Sec-Purpose: prefetch).
*/
private function is_probe_request(): bool {
if (strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')) === 'HEAD') {
return true;
}
$purpose = strtolower((string) ($_SERVER['HTTP_SEC_PURPOSE'] ?? ($_SERVER['HTTP_PURPOSE'] ?? '')));
return $purpose !== '' && str_contains($purpose, 'prefetch');
}
/**
* Emit the attachment headers for a local download.
*/
private function send_download_headers(string $path): void {
$filename = basename($path);
$size = filesize($path);
if ($size === false) {
$this->fail_410();
}
nocache_headers();
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . rawurlencode($filename) . '"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . (string) $size);
}
/**
* Stream the local file body after its headers. Returns true only when
* every byte was flushed to the client.
*/
private function stream_body(string $path): bool {
$size = filesize($path);
if ($size === false) {
$this->fail_410();
}
$chunk = 1024 * 64; // 64KB
$fh = fopen($path, 'rb');
if (!$fh) {
$this->fail_410();
}
// Disable output compression so Content-Length remains accurate.
if (function_exists('apache_setenv')) {
@apache_setenv('no-gzip', '1');
}
@ini_set('zlib.output_compression', 'Off');
while (!feof($fh)) {
if (connection_aborted()) {
fclose($fh);
return false;
}
$buf = fread($fh, $chunk);
if ($buf === false) {
fclose($fh);
return false;
}
echo $buf;
if (function_exists('flush')) {
flush();
}
}
fclose($fh);
return !connection_aborted();
}
/**
* Map a site-local URL to a filesystem path under uploads (or ABSPATH).
*/
@@ -388,54 +462,6 @@ class Download {
return '';
}
/**
* Stream a local file. Returns true only when the body was sent in full.
*/
private function stream_local_file(string $path): bool {
$filename = basename($path);
$size = filesize($path);
if ($size === false) {
$this->fail_410();
}
nocache_headers();
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . rawurlencode($filename) . '"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . (string) $size);
$chunk = 1024 * 64; // 64KB
$fh = fopen($path, 'rb');
if (!$fh) {
$this->fail_410();
}
// Disable output compression so Content-Length remains accurate.
if (function_exists('apache_setenv')) {
@apache_setenv('no-gzip', '1');
}
@ini_set('zlib.output_compression', 'Off');
while (!feof($fh)) {
if (connection_aborted()) {
fclose($fh);
return false;
}
$buf = fread($fh, $chunk);
if ($buf === false) {
fclose($fh);
return false;
}
echo $buf;
if (function_exists('flush')) {
flush();
}
}
fclose($fh);
return !connection_aborted();
}
/**
* Count a delivered download. The guard caps concurrent finishers at
* max_uses instead of overshooting the counter.