Vue3使用shpjs v5.0.1解析shp文件时出现Zip格式错误
Vue3使用shapefile-js解析SHP文件报错解决
问题场景
我在Vue3项目中使用shapefile-js(版本^5.0.1)加载SHP文件,采用Element Plus的el-upload组件实现文件上传,核心代码如下:
<el-upload ref="uploadRef" action="/" v-model:file-list="state.uploadList" :on-change="uploadFile" > <template #trigger> <el-button type="primary">选择文件</el-button> </template> </el-upload>
import shp from 'shpjs'; import { FeatureCollection } from 'geojson'; const uploadFile = async (file) => { const format = file.name.split('.').at(-1).toLowerCase(); let geojson: FeatureCollection<any>; switch (format) { case 'shp': { console.log( await file.raw.arrayBuffer() ); const parsed = await shp(await file.raw.arrayBuffer()); geojson = parsed; break; } } }
执行await file.raw.arrayBuffer()能正常输出:
ArrayBuffer(59664156) byteLength: 59664156
但调用shp(await file.raw.arrayBuffer())解析时抛出错误:
Uncaught (in promise) Error: Can't find end of central directory : is this a zip file ? at h.readEndOfCentral (shpjs.js?v=9c11b5bb:1045:63) at h.load (shpjs.js?v=9c11b5bb:1065:40) at shpjs.js?v=9c11b5bb:290:23 at async unzip_default (shpjs.js?v=9c11b5bb:6488:3) at async parseZip (shpjs.js?v=9c11b5bb:6970:15) at async Module.loadGeojson (shp.ts:61:24)
问题原因
shapefile-js的shp()核心函数默认将传入的ArrayBuffer当作ZIP压缩包解析,但单个SHP文件并不是ZIP格式,且SHP本身仅存储几何数据,必须配合.shx(索引文件)、.dbf(属性文件)等配套文件才能完整解析。直接传入单个SHP文件的buffer,会触发zip解析逻辑,导致报错。
解决方案
方案1:上传包含完整文件的ZIP包
将SHP配套的所有文件(.shp、.shx、.dbf等)打包成ZIP文件上传,此时shp()函数可以正常解析整个shapefile套件,代码调整如下:
const uploadFile = async (file) => { const format = file.name.split('.').at(-1).toLowerCase(); let geojson: FeatureCollection<any>; switch (format) { case 'zip': { const buffer = await file.raw.arrayBuffer(); geojson = await shp(buffer); break; } } }
方案2:单独解析单个SHP文件(仅几何数据)
如果仅需获取SHP文件的几何数据,可使用shapefile-js提供的parseShp方法单独解析,但这样会丢失属性数据(属性存储在.dbf中):
const uploadFile = async (file) => { const format = file.name.split('.').at(-1).toLowerCase(); let geojson: FeatureCollection<any>; switch (format) { case 'shp': { const buffer = await file.raw.arrayBuffer(); // 单独解析SHP几何数据 const geometries = await shp.parseShp(buffer); geojson = { type: 'FeatureCollection', features: geometries.map(geom => ({ type: 'Feature', geometry: geom, properties: {} // 无dbf则属性为空 })) }; break; } // 若需属性数据,需单独上传dbf文件并解析 case 'dbf': { const buffer = await file.raw.arrayBuffer(); const properties = await shp.parseDbf(buffer); console.log("属性数据:", properties); break; } } }
内容的提问来源于stack exchange,提问作者user824624
相关产品推荐
相关产品推荐

