# GeoJSON加载问题修复说明 ## 问题描述 用户上传的自定义数据(SHP文件)转换为GeoJSON后,存放在 `uploads/models/geojson/` 目录中。在开发环境下可以正常加载,但打包后无法加载,报错"加载GeoJSON失败"。 而同样在 `uploads/models/` 目录下的模型文件(.glb)却可以正常加载。 ## 问题原因 ### 模型文件 vs GeoJSON文件加载方式对比 #### 模型文件(可以正常加载) **加载方式:** 通过后端API下载 **代码位置:** `aside.vue` 第734-735行 ```javascript 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 ``` #### GeoJSON文件(打包后加载失败) **原加载方式:** 直接使用文件路径 **代码位置:** `layerManagement.js` 第507行 ```javascript const loadPromise = Cesium.GeoJsonDataSource.load(url, { ... }); ``` **实际请求路径:** ``` /uploads/models/geojson/xxx.geojson ``` ### 为什么打包后失败? **开发环境:** - Vite开发服务器会代理所有请求到后端 - 相对路径 `/uploads/...` 可以通过代理访问到后端文件 **生产环境(打包后):** - 前端和后端分离部署 - 前端静态文件服务器(Nginx/IIS)找不到 `/uploads/...` 路径的文件 - 需要通过后端API访问:`/prod-api/common/download/resource?resource=uploads/...` ## 解决方案 ### 修改内容 修改了 [layerManagement.js](file:///d:/Web/PlatformModel/RuoYi-Vue3/src/supermap-cesium-module/js/common/layerManagement.js) 文件: #### 1. 导入认证函数 ```javascript import { getToken } from '@/utils/auth'; ``` #### 2. 修改 `addGeoJsonLayer` 函数 添加本地文件检测,自动使用API加载: ```javascript 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直接加载 // ... 省略部分代码 } ``` #### 3. 新增 `loadGeoJsonViaApi` 函数 专门处理本地GeoJSON文件的加载: ```javascript 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); } ``` #### 4. 同样修改 `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 ↓ 加载成功 ``` ### 关键技术点 1. **路径检测**:自动识别本地文件路径(`/uploads/` 开头) 2. **API调用**:使用后端 `/common/download/resource` 接口下载文件 3. **认证集成**:自动添加 `Authorization` header 4. **Blob处理**:将下载的文件转换为 Blob URL 供 Cesium 使用 5. **内存管理**:加载完成后自动释放 Blob URL ## 验证步骤 ### 1. 重新打包 ```bash cd d:\Web\PlatformModel\RuoYi-Vue3 npm run build:prod ``` ### 2. 查看控制台日志 成功加载时应该看到: ``` ========== 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加载成功 ========== 图层名称: 自定义数据 ``` ### 3. 检查网络请求 打开浏览器开发者工具 → Network 标签: 应该看到: - 请求URL:`/prod-api/common/download/resource?resource=uploads%2Fmodels%2Fgeojson%2Fxxx.geojson` - 状态:`200 OK` - 类型:`application/octet-stream` ## 支持的文件路径格式 修改后的代码支持以下格式的本地路径: - ✅ `/uploads/models/geojson/xxx.geojson` - ✅ `uploads/models/geojson/xxx.geojson` - ✅ `./uploads/models/geojson/xxx.geojson` ## 注意事项 ### 1. 后端API要求 确保后端提供了 `/common/download/resource` 接口,且: - 支持GeoJSON文件下载 - 返回正确的文件内容 - 支持认证 ### 2. 文件权限 确保: - uploads 目录存在且可访问 - geojson 文件有正确的读取权限 ### 3. 外部URL不受影响 外部URL(如超图服务、在线GeoJSON)仍然直接加载,不通过API。 ### 4. 内存管理 代码会自动释放Blob URL,无需手动管理。 ## 相关文件 - [layerManagement.js](file:///d:/Web/PlatformModel/RuoYi-Vue3/src/supermap-cesium-module/js/common/layerManagement.js) - 主要修改文件 - [aside.vue](file:///d:/Web/PlatformModel/RuoYi-Vue3/src/supermap-cesium-module/views/layout/aside.vue) - 参考模型加载方式 - [auth.js](file:///d:/Web/PlatformModel/RuoYi-Vue3/src/utils/auth.js) - 认证函数 ## 常见问题 ### Q: 为什么模型文件可以加载,GeoJSON不行? A: 模型文件通过后端API下载,GeoJSON直接使用文件路径。打包后前端静态服务器找不到文件。 ### Q: 修改后会影响性能吗? A: 影响很小。多了一次API请求,但文件下载速度与直接访问相同。 ### Q: 外部URL也会通过API加载吗? A: 不会。只有以 `/uploads/` 开头的本地路径才会通过API加载。 ### Q: 需要修改数据库中的路径吗? A: 不需要。数据库中的路径保持不变,代码会自动处理。 ## 总结 通过让GeoJSON文件和模型文件使用相同的加载方式(通过后端API),解决了打包后无法加载本地GeoJSON文件的问题。代码会自动识别本地路径并进行相应处理,对用户透明。