使用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
相关产品推荐
相关产品推荐

