You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Fetch跨域获取JSON遇CORS问题,PHP代理如何返回文件并设缓存?

解决方案:PHP代理返回文件并设置缓存头

当然可以。你只需要在PHP代理中添加正确的缓存响应头,同时返回文件的原始MIME类型,让浏览器识别并缓存这个资源。

改进后的PHP代码

// 允许跨域
header('Access-Control-Allow-Origin: *');

// 目标文件路径
$filePath = 'data.json';

// 检查文件是否存在
if (!file_exists($filePath)) {
    http_response_code(404);
    echo json_encode(['error' => 'File not found']);
    exit;
}

// 获取文件的基本信息
$fileMtime = filemtime($filePath);
$fileSize = filesize($filePath);
$etag = md5_file($filePath);

// 设置缓存相关头
// 缓存有效期,这里设为7天,可根据需求调整
$maxAge = 60 * 60 * 24 * 7;
header("Cache-Control: public, max-age=$maxAge");
header("Expires: " . gmdate('D, d M Y H:i:s', time() + $maxAge) . ' GMT');
header("Last-Modified: " . gmdate('D, d M Y H:i:s', $fileMtime) . ' GMT');
header("ETag: \"$etag\"");

// 检查客户端缓存是否有效,避免重复返回文件
$ifModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false;
$ifNoneMatch = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? $_SERVER['HTTP_IF_NONE_MATCH'] : false;

if (($ifModifiedSince && strtotime($ifModifiedSince) === $fileMtime) || ($ifNoneMatch && trim($ifNoneMatch) === "\"$etag\"")) {
    http_response_code(304);
    exit;
}

// 设置文件MIME类型
header('Content-Type: application/json');
header("Content-Length: $fileSize");

// 输出文件内容(比file_get_contents更高效,适合大文件)
readfile($filePath);
exit;

关键说明

  • 缓存头设置:通过Cache-Control、Expires指定缓存时长,Last-Modified和ETag用于验证客户端缓存是否过期,当资源未更新时返回304状态码,减少带宽消耗。
  • MIME类型:明确设置Content-Type: application/json,让浏览器识别这是JSON资源,确保正确处理和缓存。
  • 高效输出:用readfile()替代file_get_contents(),直接输出文件内容,无需把整个文件读入内存,性能更好。
  • 缓存验证:检查客户端请求头If-Modified-Since和If-None-Match,如果缓存有效就返回304,不重复发送文件内容。

前端Fetch的适配

前端代码无需修改,但浏览器会自动根据PHP返回的缓存头处理缓存,后续请求会直接读取本地缓存,直到缓存过期或资源更新。

内容的提问来源于stack exchange,提问作者Runnick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 03:01:07