用户上传的自定义数据(SHP文件)转换为GeoJSON后,存放在 uploads/models/geojson/ 目录中。在开发环境下可以正常加载,但打包后无法加载,报错"加载GeoJSON失败"。
而同样在 uploads/models/ 目录下的模型文件(.glb)却可以正常加载。
加载方式: 通过后端API下载
代码位置: aside.vue 第734-735行
const baseURL = import.meta.env.VITE_APP_BASE_API || ''
const apiUrl = baseURL + "/common/download/resource?resource=" + encodeURIComponent(modelUrl)
实际请求路径:
/prod-api/common/download/resource?resource=uploads/models/xxx.glb
原加载方式: 直接使用文件路径
代码位置: layerManagement.js 第507行
const loadPromise = Cesium.GeoJsonDataSource.load(url, { ... });
实际请求路径:
/uploads/models/geojson/xxx.geojson
开发环境:
/uploads/... 可以通过代理访问到后端文件生产环境(打包后):
/uploads/... 路径的文件/prod-api/common/download/resource?resource=uploads/...修改了 layerManagement.js 文件:
import { getToken } from '@/utils/auth';
addGeoJsonLayer 函数添加本地文件检测,自动使用API加载:
function addGeoJsonLayer(url, name, callback) {
// ... 省略部分代码
// 检查是否为本地文件路径(需要通过API加载)
const isLocalPath = url.startsWith('/uploads/') || url.startsWith('uploads/') || url.startsWith('./uploads/');
if (isLocalPath) {
console.log('检测到本地GeoJSON文件,通过API加载:', url);
loadGeoJsonViaApi(url, name, null, callback);
return;
}
// 外部URL直接加载
// ... 省略部分代码
}
loadGeoJsonViaApi 函数专门处理本地GeoJSON文件的加载:
async function loadGeoJsonViaApi(url, name, style, callback) {
// 1. 规范化URL
let normalizedUrl = url.replace(/^\/+/, '').replace(/^\.\/+/, '');
// 2. 构建API URL
const baseURL = window.globalRequestConfig?.baseURL || import.meta.env.VITE_APP_BASE_API || '';
const apiUrl = `${baseURL}/common/download/resource?resource=${encodeURIComponent(normalizedUrl)}`;
// 3. 获取认证token
const token = typeof getToken === 'function' ? 'Bearer ' + getToken() : '';
// 4. 通过API下载文件
const response = await fetch(apiUrl, {
method: 'GET',
headers: { 'Authorization': token }
});
// 5. 创建Blob URL
const blob = await response.blob();
const blobUrl = URL.createObjectURL(blob);
// 6. 使用Cesium加载
const loadPromise = Cesium.GeoJsonDataSource.load(blobUrl, { ... });
// 7. 加载完成后释放Blob URL
URL.revokeObjectURL(blobUrl);
}
addGeoJsonLayerWithStyle 函数添加了相同的本地文件检测和API加载逻辑。
GeoJSON URL: /uploads/models/geojson/xxx.geojson
↓
直接请求前端服务器
↓
404 Not Found(文件不存在)
GeoJSON URL: /uploads/models/geojson/xxx.geojson
↓
检测为本地文件
↓
转换为API URL: /prod-api/common/download/resource?resource=uploads/models/geojson/xxx.geojson
↓
请求后端API下载文件
↓
创建Blob URL
↓
Cesium加载Blob URL
↓
加载成功
/uploads/ 开头)/common/download/resource 接口下载文件Authorization headercd d:\Web\PlatformModel\RuoYi-Vue3
npm run build:prod
成功加载时应该看到:
========== addGeoJsonLayer 开始执行 ==========
URL: uploads/models/geojson/xxx.geojson
Name: 自定义数据
检测到本地GeoJSON文件,通过API加载: uploads/models/geojson/xxx.geojson
========== loadGeoJsonViaApi 开始执行 ==========
原始URL: uploads/models/geojson/xxx.geojson
API URL: /prod-api/common/download/resource?resource=uploads%2Fmodels%2Fgeojson%2Fxxx.geojson
开始通过API下载GeoJSON文件...
API响应状态: 200
文件大小: 12345 bytes
创建Blob URL: blob:http://localhost/xxx-xxx-xxx
开始使用Cesium加载GeoJSON...
========== GeoJSON通过API加载成功 ==========
图层名称: 自定义数据
打开浏览器开发者工具 → Network 标签:
应该看到:
/prod-api/common/download/resource?resource=uploads%2Fmodels%2Fgeojson%2Fxxx.geojson200 OKapplication/octet-stream修改后的代码支持以下格式的本地路径:
/uploads/models/geojson/xxx.geojsonuploads/models/geojson/xxx.geojson./uploads/models/geojson/xxx.geojson确保后端提供了 /common/download/resource 接口,且:
确保:
外部URL(如超图服务、在线GeoJSON)仍然直接加载,不通过API。
代码会自动释放Blob URL,无需手动管理。
A: 模型文件通过后端API下载,GeoJSON直接使用文件路径。打包后前端静态服务器找不到文件。
A: 影响很小。多了一次API请求,但文件下载速度与直接访问相同。
A: 不会。只有以 /uploads/ 开头的本地路径才会通过API加载。
A: 不需要。数据库中的路径保持不变,代码会自动处理。
通过让GeoJSON文件和模型文件使用相同的加载方式(通过后端API),解决了打包后无法加载本地GeoJSON文件的问题。代码会自动识别本地路径并进行相应处理,对用户透明。