导入效果:
用到的npm库
pnpm add shpjs // 或者 npm i shpjs 5.0.2
pnpm add jszip // 或者 npm i jszip 版本3.10.1
pnpm add @tmcw/togeojson // 或者 npm i @tmcw/togeojson 版本 5.8.1
创建方法用来区分导入的文件
1. 这里只是做了一个文件的区分 其中的kmlToGeoJson 和 readShp 、dealZip 具体方法会写明
// 处理文件
export const dealFile = async (file: UploadFile) => {
let geoJson = undefined
if (!file?.raw) return
try {
if (file?.name?.includes('.kml')) geoJson = await kmlToGeoJson(file.raw)
else if (file?.name?.includes('.shp') || file?.name?.includes('.zip')) geoJson = await readShp(file.raw)
else if (file?.name?.includes('.zip')) geoJson = await dealZip(file.raw)
else ElMessage.warning(`本系统暂只支持${fileType}文件`)
} catch (err) {
}
return geoJson
}
kml转换geojson
import {kml} from "@tmcw/togeojson";
const kmlToGeoJson = (file: UploadRawFile) => {
let reader = new FileReader()
reader.readAsText(file)
return new Promise((resolve, reject) => {
reader.onload = (e) => {
// @ts-ignore 读取文件内容
const fileString = e.target.result
let geoJson = kml(new DOMParser().parseFromString(fileString as string, "text/xml"))
resolve(geoJson)
}
reader.onerror = () => {
ElMessage.error('kml文件读取失败') // 这个是ui报错可以不管他
reject(reader.error)
}
})
}
shp转geojson
其中的方法dealZip 主要是处理压缩包的 shp文件有好多个合在一起的 不能单独传,单独传会报错。把所有的文件打包成一个压缩包在进行上传就可以了。
这里注意shp 不能直接引入shpjs 只能向我这种引入
import shp from 'shpjs/dist/shp.js'
import JsZip from 'jszip'
// shapefile插件 shp转geo
const shpToGeoJson = async (data: ArrayBuffer) => {
try {
return await shp(data)
} catch (e) {
ElMessage.error('shp文件读取失败')
}
}
const readShp = (file: UploadRawFile) => {
let fileReader = new FileReader();
fileReader.readAsArrayBuffer(file);
return new Promise((resolve, reject) => {
fileReader.onload = async (e) => {
let fileString = e.target?.result
let geoJson = fileString && await shpToGeoJson(<ArrayBuffer>fileString)
geoJson && resolve(geoJson)
geoJson || reject()
}
fileReader.onerror = () => {
ElMessage.error('shp文件读取失败')
reject(fileReader.error)
}
})
}
// 处理压缩包
const dealZip = async (file: UploadRawFile) => {
const newZip = new JsZip()
const res = await newZip.loadAsync(file)
const fileList = Object.keys(res.files)
const pattern = new RegExp(/\S\.shp$/)
let shpFile = fileList.find(i => pattern.test(i))
try {
// @ts-ignore
let res = await newZip.file(shpFile).async('arraybuffer')
return await shpToGeoJson(res)
} catch (err) {
ElMessage.error('shp文件读取失败')
}
}
完整代码
// 把kml 文件解析为geoJson
import {kml} from "@tmcw/togeojson";
// @ts-ignore 解析shp 文件
import shp from 'shpjs/dist/shp.js'
import JsZip from 'jszip'
import {ElMessage} from "element-plus";
import type {UploadFile, UploadRawFile} from "element-plus/lib/components/upload/src/upload";
export const fileType = ['kml', 'shp', 'zip']
// 把kml 文件转换为geoJson
const kmlToGeoJson = (file: UploadRawFile) => {
let reader = new FileReader()
reader.readAsText(file)
return new Promise((resolve, reject) => {
reader.onload = (e) => {
// @ts-ignore 读取文件内容
const fileString = e.target.result
let geoJson = kml(new DOMParser().parseFromString(fileString as string, "text/xml"))
resolve(geoJson)
}
reader.onerror = () => {
ElMessage.error('kml文件读取失败')
reject(reader.error)
}
})
}
// shapefile插件 shp转geo
const shpToGeoJson = async (data: ArrayBuffer) => {
try {
return await shp(data)
} catch (e) {
ElMessage.error('shp文件读取失败')
}
}
const readShp = (file: UploadRawFile) => {
let fileReader = new FileReader();
fileReader.readAsArrayBuffer(file);
return new Promise((resolve, reject) => {
fileReader.onload = async (e) => {
let fileString = e.target?.result
let geoJson = fileString && await shpToGeoJson(<ArrayBuffer>fileString)
geoJson && resolve(geoJson)
geoJson || reject()
}
fileReader.onerror = () => {
ElMessage.error('shp文件读取失败')
reject(fileReader.error)
}
})
}
// 处理压缩包
const dealZip = async (file: UploadRawFile) => {
const newZip = new JsZip()
const res = await newZip.loadAsync(file)
const fileList = Object.keys(res.files)
const pattern = new RegExp(/\S\.shp$/)
let shpFile = fileList.find(i => pattern.test(i))
try {
// @ts-ignore
let res = await newZip.file(shpFile).async('arraybuffer')
return await shpToGeoJson(res)
} catch (err) {
ElMessage.error('shp文件读取失败')
}
}
// 处理文件
export const dealFile = async (file: UploadFile) => {
let geoJson = undefined
if (!file?.raw) return
try {
if (file?.name?.includes('.kml')) geoJson = await kmlToGeoJson(file.raw)
else if (file?.name?.includes('.shp') || file?.name?.includes('.zip')) geoJson = await readShp(file.raw)
else if (file?.name?.includes('.zip')) geoJson = await dealZip(file.raw)
else ElMessage.warning(`本系统暂只支持${fileType}文件`)
} catch (err) {
}
return geoJson
}
解析kml shp内的附带字段
1.shp的附带值是features[i].properties里的 基本不需要处理
2,kml附带值 在features[i].properties?.description?.value里 是个html格式的文本字段 里面的字段包裹在trtd 里面
let modifyTheDivOfTheValue: HTMLElement
function initUpload() {
// 创建div 方便提前geoJson 值 创建一个div 并且一直使用一个div最后删除它
modifyTheDivOfTheValue = document.createElement('div')
}
// 结束上传
function endUpload() {
modifyTheDivOfTheValue?.remove?.()
}
// html 中获取tr td 数据并且转为对象格式
function conversion(html: string) {
try {
if (!html) return
modifyTheDivOfTheValue.innerHTML = html
// 获取所有 <tr> 元素
const rows = modifyTheDivOfTheValue.querySelectorAll('tr');
// 初始化结果对象
const result: any = {};
// 遍历所有 <tr> 元素
rows.forEach(row => {
// 获取当前 <tr> 元素内的所有 <td> 元素
const cells = row.querySelectorAll('td');
// 检查 <td> 元素是否成对出现
if (cells.length === 2) {
// 将键值对添加到结果对象中 获取第一个 <td> 的文本内容作为键 获取第二个 <td> 的文本内容作为值
result[cells[0].innerText] = cells[1].innerText
}
});
return result
} catch (err) {
return ''
}
}
循环geojson 值
for (let i = 0; i < features?.length; i++) {
let description = features[i].properties?.description?.value
let result = conversion(description)
}