如何阻止浏览器缓存JSON文件?无服务器Root权限的实现方案
解决Chrome缓存JSON文件导致内容不更新的问题
我做了一个从JSON文件读取内容并展示表格的小型网站,功能正常,但Chrome总是缓存这个JSON文件,必须频繁按Shift+F5强制刷新才能看到更新内容。我不想让网站使用者手动修改浏览器设置,而且没有服务器Root权限没法改服务器配置,希望通过脚本或PHP代码解决这个问题。
以下是相关代码:
数据更新页面(updater)
<!DOCTYPE html> <html> <head> <title>Test-Updater</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> </head> <body> <br /> <div class="container" style="width:500px;"> <h3 align="">Append Data to JSON File</h3><br/> <form method="post" action="jsonproc.php"> <br /> <label>Titel</label> <input type="text" name="title" class="form-control"/><br/> <label>Genre</label> <input type="text" name="genre" class="form-control"/><br/> <label>Bewertung</label> <input type="text" name="rating" class="form-control"/><br/> <input type="submit" name="submit" value="Append" class="btn btn-info"/><br/> </form> </div> <br /> </body> </html>
数据展示页面(Viewer)
<!DOCTYPE html> <html> <head> <title>Sample Test Page</title> </head> <body> <h2>Movie List</h2> <table id = "tb1" border = "1"> <tr> <th>Titel</th> <th>Genre</th> <th>Bewertung</th> </tr> </table> <script> fetch("boli.db") .then(response => response.json()) .then(data => { for (var i = 0; i<data.movies.length; i++){ let vtitle = data.movies[i].title; let vgenre = data.movies[i].genre; let vrating = data.movies[i].rating; document.querySelector("#tb1").innerHTML += ` <tr> <td>${vtitle}</td> <td>${vgenre}</td> <td>${vrating}</td> </tr>`; } }) </script> </body> </html>
JSON处理脚本(jsonproc.php)
<?php $title = $_POST['title']; $genre = $_POST['genre']; $rating = $_POST['rating']; $file_name='boli.db'; if(file_exists("$file_name")) { $db_data= file_get_contents($file_name); $decoded_data = json_decode($db_data, true); $new_data['title'] = $title; $new_data['genre'] = $genre; $new_data['rating'] = $rating; array_push($decoded_data['movies'], array('title' => $new_data['title'], 'genre' => $new_data['genre'], 'rating' => $new_data['rating'])); $jsonData = json_encode($decoded_data); file_put_contents($file_name, $jsonData); unset($decoded_data); } else { echo "file not exist<br/>"; } ?>
解决方案
方法1:给请求URL添加随机参数(前端脚本修改)
浏览器会认为带不同参数的URL是不同资源,不会缓存旧内容。修改展示页面的fetch代码:
// 生成时间戳作为随机参数 const timestamp = new Date().getTime(); fetch(`boli.db?t=${timestamp}`) .then(response => response.json()) .then(data => { // 原处理逻辑不变 for (var i = 0; i<data.movies.length; i++){ let vtitle = data.movies[i].title; let vgenre = data.movies[i].genre; let vrating = data.movies[i].rating; document.querySelector("#tb1").innerHTML += ` <tr> <td>${vtitle}</td> <td>${vgenre}</td> <td>${vrating}</td> </tr>`; } })
方法2:用PHP代理JSON请求(添加缓存控制头)
创建一个PHP文件(比如get_json.php),读取JSON文件并输出,同时设置禁止缓存的响应头:
<?php $file_name = 'boli.db'; if (file_exists($file_name)) { // 设置禁止缓存的HTTP头 header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1 header("Pragma: no-cache"); // HTTP 1.0 header("Expires: 0"); // Proxies // 输出JSON内容 header('Content-Type: application/json'); echo file_get_contents($file_name); } else { http_response_code(404); echo json_encode(['error' => 'File not found']); } ?>
然后修改展示页面的fetch目标为这个PHP文件:
fetch("get_json.php") .then(response => response.json()) .then(data => { // 原处理逻辑不变 for (var i = 0; i<data.movies.length; i++){ let vtitle = data.movies[i].title; let vgenre = data.movies[i].genre; let vrating = data.movies[i].rating; document.querySelector("#tb1").innerHTML += ` <tr> <td>${vtitle}</td> <td>${vgenre}</td> <td>${vrating}</td> </tr>`; } })
方法3:更新JSON文件时记录修改时间,请求时带上该时间戳(结合前后端)
在jsonproc.php中,每次更新JSON文件后,保存一个修改时间戳到文件(比如last_update.txt):
<?php $title = $_POST['title']; $genre = $_POST['genre']; $rating = $_POST['rating']; $file_name='boli.db'; $timestamp_file = 'last_update.txt'; if(file_exists("$file_name")) { $db_data= file_get_contents($file_name); $decoded_data = json_decode($db_data, true); $new_data['title'] = $title; $new_data['genre'] = $genre; $new_data['rating'] = $rating; array_push($decoded_data['movies'], array('title' => $new_data['title'], 'genre' => $new_data['genre'], 'rating' => $new_data['rating'])); $jsonData = json_encode($decoded_data); file_put_contents($file_name, $jsonData); // 保存当前时间戳 file_put_contents($timestamp_file, time()); unset($decoded_data); } else { echo "file not exist<br/>"; } ?>
然后在展示页面,先请求这个时间戳,再带上它请求JSON:
fetch("last_update.txt") .then(response => response.text()) .then(timestamp => { return fetch(`boli.db?t=${timestamp}`); }) .then(response => response.json()) .then(data => { // 原处理逻辑不变 for (var i = 0; i<data.movies.length; i++){ let vtitle = data.movies[i].title; let vgenre = data.movies[i].genre; let vrating = data.movies[i].rating; document.querySelector("#tb1").innerHTML += ` <tr> <td>${vtitle}</td> <td>${vgenre}</td> <td>${vrating}</td> </tr>`; } })
内容的提问来源于stack exchange,提问作者FadeBeatz Official
相关产品推荐
相关产品推荐

