CI4静态KML文件CORS问题:Nuxt.js前端访问及构建后更新异常
我使用Nuxt.js前端访问CodeIgniter4(CI4)/public目录下的KML文件,通过Omnivore加载KML资源时出现CORS错误,提示请求资源缺少Access-Control-Allow-Origin响应头。已在CI4中配置CORS中间件,开发环境下可正常访问,但应用构建完成后,无法更新或新增KML文件。
前端代码
try { for (const city of this.cities) { if (!city || !city.kml) { continue; } const baseURL = `http://localhost:8080`; const kmlFilePath = baseURL + city.kml; Omnivore.kml(kmlFilePath).addTo(customIcons); } } catch (error) { console.error('Error fetching or adding KMZ file:', error); }
错误信息
Access to XMLHttpRequest at 'http://localhost:8080/uploads/transmitters/kmz/Untitled.kml' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
GET http://localhost:8080/uploads/transmitters/kmz/Untitled.kml net::ERR_FAILED 200 (OK)
CI4的CORS中间件配置代码
public function before(RequestInterface $request, $arguments = null) { header('Access-Control-Allow-Origin: *'); header("Access-Control-Allow-Headers: Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method"); header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE"); header('Access-Control-Allow-Credentials: true'); $method = $_SERVER['REQUEST_METHOD']; if($method == "OPTIONS") { die(); }; }
解决思路
1. 核心问题:静态资源未经过CI4中间件
你访问的KML文件位于/uploads目录下,默认情况下CI4的public目录静态资源由Web服务器(Nginx/Apache)直接处理,不会走CI4的中间件流程,所以你配置的CORS头根本没生效。开发环境用CI4内置服务器时,静态资源会经过框架,所以能正常访问;生产环境用正式Web服务器,直接返回文件,没带CORS头。
2. 直接修改Web服务器配置(推荐)
Nginx配置
在对应server块中添加:
location ~* \.(kml|kmz)$ { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods GET,POST,OPTIONS; add_header Access-Control-Allow-Headers Authorization,X-API-KEY,Origin,X-Requested-With,Content-Type,Accept,Access-Control-Request-Method; if ($request_method = OPTIONS) { return 204; } }
Apache配置
在项目根目录的.htaccess文件中添加:
<FilesMatch "\.(kml|kmz)$"> Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Methods "GET,POST,OPTIONS" Header set Access-Control-Allow-Headers "Authorization,X-API-KEY,Origin,X-Requested-With,Content-Type,Accept,Access-Control-Request-Method" </FilesMatch> RewriteEngine On RewriteCond %{REQUEST_METHOD} OPTIONS RewriteRule ^(.*)$ $1 [R=204,L]
3. 让静态资源走CI4中间件(备选)
如果无法修改Web服务器配置,可通过路由转发让文件请求经过CI4中间件:
- 在
Routes.php中添加路由:
$routes->get('uploads/(:any)', 'FileController::serve/$1');
- 创建
FileController控制器:
<?php namespace App\Controllers; use CodeIgniter\Controller; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; use Psr\Log\LoggerInterface; class FileController extends Controller { public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) { parent::initController($request, $response, $logger); // 添加CORS头 $this->response->setHeader('Access-Control-Allow-Origin', '*'); $this->response->setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS'); $this->response->setHeader('Access-Control-Allow-Headers', 'Authorization,X-API-KEY,Origin,X-Requested-With,Content-Type,Accept,Access-Control-Request-Method'); } public function serve($path) { $filePath = FCPATH . 'uploads/' . $path; if (!file_exists($filePath)) { return $this->response->setStatusCode(404); } return $this->response->download($filePath, null); } }
4. 检查前端构建后的baseURL
确保构建后的前端baseURL配置与生产环境域名一致,避免因来源不匹配导致的跨域问题。
内容的提问来源于stack exchange,提问作者noir

