Skip to content

数据管理

上传文件

上传文件示例

使用 tus 以实现分片上传,上传参数见数据发布参数

tus 库详细配置参考https://github.com/tus/tus-js-client/blob/main/docs/api.md

上传同时需要使用的函数

获取 proj4getPROJ4;

上传初始化uploadInit

ts
getFileAndUpload()
/**示例上传-上传osgb并发布 */
function getFileAndUpload() {
  const file = new File([''], 'osgb.zip') //自行获取File对象,这里只是示例
  tusExample_upload_osgb_lonlat_mode(file)
}

type uploadInitData = {
  bizType: string | undefined //数据的业务类型(参考下表)
  fileName: string | undefined //文件名(带后缀名)
  cfgJson: string | undefined //配置信息(参考下表)(isPublish为"0"时cfgJson为"")
  isPublish: string //是否发布 "0"为不发布,"1"为发布
  fileType: string | undefined //文件类型(参考下表)
  projectId: string | undefined //项目id
  folderId: string | undefined //文件夹id,公共数据根目录为"0",且projectId为""
}
/**
 * @description 上传文件示例
 * @param file 文件
 * @param initParams 初始化参数
 */
async function uploadFileByTusExample(file: File, initParams: uploadInitData) {
  //调用上传初始化接口
  const res = await uploadInit(initParams) //上传初始化,参数见下方
  const dataId = res.data.id
  const upload = new tus.Upload(file, {
    endpoint: CONSTANTS.API_URL + '/admin/api/files/upload',
    retryDelays: [0, 3000, 5000, 10000, 20000],
    headers: {
      Authorization: `Bearer ${CONSTANTS.TOKEN}`, //token
      dataId: dataId //上传初始化获取的dataId
    },
    metadata: {
      folderId: initParams.folderId ?? '0', //文件夹id
      projectId: initParams.projectId ?? '', //项目id
      dataId //上传初始化获取的dataId
    },
    chunkSize: 6 * 1024 * 1024, //分片大小,过大可能会导致上传失败
    storeFingerprintForResuming: false, //是否存储指纹,用于续传,这里不续传
    onAfterResponse: (_req, res) => {
      const getHeader = res.getHeader.bind(res)
      res.getHeader = (header: string) => {
        //用于修改上传请求返回的location,这里用于拼接完整的url
        if (header === 'Location') {
          return CONSTANTS.API_URL + getHeader(header)
        }
        if (header === 'Upload-Length') {
          //返回文件大小
          return file.size.toString()
        }
        return getHeader(header)
      }
    },
    //上传失败回调
    onError: function (error) {
      console.log('Failed because: ' + error)
    },
    //上传进度回调
    onProgress: function (bytesUploaded, bytesTotal) {
      var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2)
      console.log(bytesUploaded, bytesTotal, percentage + '%')
    },
    //上传成功回调
    onSuccess: function () {
      const fileName =
        upload.file instanceof File ? upload.file.name : 'unknown'
      console.log(fileName + 'uploaded successfully')
    }
  })
  upload.start() //开始/继续上传 //upload.abort() //暂停上传 //upload.abort(true) //终止上传
}

/**上传示例,上传OSGB ZIP包,并发布 */
export async function tusExample_upload_osgb_lonlat_mode(file: File) {
  //获取proj4
  const proj4 = await (async () => {
    const res = await getPROJ4({
      proType: 'Gauss-Kruger',
      ellipsoid: 'CGCS2000(国家2000)',
      subBand: '3-degree Gauss-Kruger zone 25',
      centerLon: '75',
      falseEast: '25500000',
      falseNorth: '0'
    })
    const proj4 = res?.data?.cfgRecord?.projInfo
    if (proj4) {
      return proj4
    } else {
      throw new Error('获取proj4失败')
    }
  })()
  const cfg = {
    coordType: 'LonLat',
    projectType: 'prj4',
    ellipsoidType: 'FourParam',
    ellipsoidEnabled: 0,
    ellipsoidParam: ',,,',
    projectPlaneElevation: '',
    centerPosition: '120,30,0',
    // projectParam: '+proj=tmerc +lat_0=0 +lon_0=75.00000 +k=1 +x_0=25500000.00000 +y_0=0.00000 +ellps=GRS80 +units=m +no_defs',
    projectParam: proj4
  }
  const initParams = {
    bizType: '3',
    isPublish: '1',
    fileName: 'osgb.zip',
    cfgJson: JSON.stringify(cfg),
    fileType: 'osgb',
    projectId: '',
    folderId: '0'
  }
  uploadFileByTusExample(file, initParams)
}

上传相关接口

获取 proj4

参考投影

字段值类型注释
proType'Gauss-Kruger' | 'UTM'投影类型,高斯克吕格或者 UTM
ellipsoid'CGCS2000(国家 2000)' | '西安 80' | '北京 54' | 'WGS84'椭球参数(UTM 只有 WGS84)
subBandstring坐标系
centerLonstring中央经线
falseEaststring假东
falseNorthstring假北
ts
//获取proj4
function getPROJ4(geoCoordinateInfo: {
  proType: 'Gauss-Kruger' | 'UTM' //投影类型,高斯克吕格或者UTM
  ellipsoid: 'CGCS2000(国家2000)' | '西安80' | '北京54' | 'WGS84' //椭球参数
  subBand: string //坐标系
  centerLon: string //中央经线
  falseEast: string //假东
  falseNorth: string //假北
}) {
  return request({
    url: '/admin/geo/param/transform',
    method: 'post',
    data: {
      geoCoordinateInfo
    }
  })
}

上传初始化

参考参数列表

ts
type uploadInitData = {
  bizType: string | undefined
  fileName: string | undefined
  cfgJson: string | undefined
  isPublish: string
  fileType: string | undefined
  projectId: string | undefined
  folderId: string | undefined
}
//上传初始化
function uploadInit(data: uploadInitData) {
  data.cfgJson = encodeURIComponent(data.cfgJson ?? '')
  data.fileName = encodeURIComponent(data.fileName ?? '')
  return request({
    url: '/admin/data/upload',
    method: 'post',
    data: data,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}

文件夹(文件)操作(复制、移动、重命名、删除)

ts
/**
 * 文件夹操作
 * 创建三个文件夹,复制一个文件夹,移动一个文件夹,重命名一个文件夹,删除一个文件夹
 */
async function folder_manage() {
  const [res, res1, res2] = await Promise.all([
    createFolder({ name: '测试文件夹1', parentId: '0' }),
    createFolder({ name: '测试文件夹1-1', parentId: '0' }),
    createFolder({ name: '测试文件夹to_del', parentId: '0' })
  ])
  const folderId = res.data.id
  const folderId1 = res1.data.id
  await copyFolder({ ids: folderId, parentId: '0' })
  await moveFolder({ ids: folderId1, parentId: folderId })
  await renameFileOrFolder({ name: '测试文件夹1-1_rename', id: folderId1 })
  await moveToRecycleBin({ ids: res2.data.id })
  console.log('文件夹操作完成')
}

创建文件夹

ts
/**创建文件夹 */
function createFolder(data: {
  name: string
  parentId: string
  projectId?: string
}) {
  return request({
    url: '/admin/tx/folders',
    method: 'post',
    data
  })
}

复制文件夹(文件)

ts
/**
 * @description 复制文件夹(文件)
 */
export function copyFolder(data: {
  ids: string
  parentId: string
  projectId?: string
}) {
  return request({
    url: '/admin/tx/folders/copyFolder',
    method: 'post',
    data
  })
}

移动文件夹(文件)

ts
/**
 * @description 移动文件夹
 * @param 文件夹ids,多个用逗号隔开
 * @param 父文件夹id
 * @param  项目id
 */
export function moveFolder(data: {
  ids: string
  parentId: string
  projectId?: string
}) {
  return request({
    url: '/admin/tx/folders/moveFolder',
    method: 'post',
    data
  })
}

移动到回收站

ts
/**
 * @description 移动到回收站
 * @param 文件夹/文件ids,多个用逗号隔开
 */
export function moveToRecycleBin(data: { ids: string }) {
  return request({
    url: '/admin/tx/folders/moveToRecycleBin',
    method: 'post',
    data
  })
}

重命名文件夹(文件)

ts
/**
 * @description 重命名文件夹或文件
 * @param 文件夹/文件ids,多个用逗号隔开
 */
export function renameFileOrFolder(data: { name: string; id: string }) {
  return request({
    url: '/admin/tx/folders/rename',
    method: 'post',
    data
  })
}

数据列表/发布/下载

示例

ts
/**
 * 获取数据中心数据列表,发布素材并下载
 */
async function get_data_list_and_publish_and_download() {
  //获取数据状态数据处理状态字典
  const dataStatusList = (await getDicts('data_process_status')).data.map(
    (e: any) => {
      return {
        value: Number(e.value),
        desc: e.description
      }
    }
  )
  //数据列表
  const res = await fetchDataCenterListV2({
    parentId: '0',
    size: '100',
    current: '1'
  })
  console.log('list :>> ', res.data.records)
  //假设list中有一条id为"89ae976b54517804316a83e79dbcada0"的数据
  const FILE_ID = '89ae976b54517804316a83e79dbcada0'
  const data = res.data.records.find((item: any) => item.id === FILE_ID)
  //发布数据
  await publishData({
    dataId: data.dataId, //文件dataId
    cfgJson: JSON.stringify({}), //配置信息
    fileType: 'skp',
    bizType: 8,
    folderId: data.id //id
  })
  const is_publish_success = await get_data_status(data.id, dataStatusList)
  if (!is_publish_success) {
    console.log('发布失败')
    const errorReason = (
      await fetchDataCenterListV2({
        parentId: '0',
        size: '100',
        current: '1'
      })
    ).data.records.find((item: any) => item.id === FILE_ID).errorReason
    console.log('errorReason :>> ', errorReason)
    return
  }
  //调用地图服务
  callMapService(FILE_ID)
  await storeUserInfo()
  //下载文件
  downLoadFile(FILE_ID)
  console.log('发布完成')
}

获取数据中心数据列表

ts
/**
 * 获取数据中心数据列表包括文件、文件夹
 *
 */
export function fetchDataCenterListV2(query: {
  bizType?: string
  dataStatus?: string
  endUploadDate?: string
  fileType?: string
  keyword?: string
  parentId: string
  projectId?: string
  startUploadDate?: string
  size: string
  current?: string
}) {
  return request({
    url: '/admin/tx/folders/resource/list',
    method: 'get',
    params: query
  })
}

发布数据

ts
/**发布数据 */
export function publishData(data?: Object) {
  return request({
    url: '/admin/tx/data/publish',
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    method: 'post',
    data: data
  })
}

获取数据处理进度

ts
/**获取数据处理进度,ids逗号分隔 */
export function fetchDataProcess(query?: { folderIds: string }) {
  return request({
    url: '/admin/tx/data/getDataProcess',
    method: 'get',
    params: query
  })
}
ts
/**定时获取数据处理状态 */
function get_data_status(id: string, dataStatusList: any) {
  //11:未发布
  // const not_publish = 11;
  const published = 52
  //错误代码,errorReason里会有错误信息
  const errorCodes = [23, 33, 43, 53]
  //处理中代码getDicts('data_process_status')
  // const processCodes = [20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51];
  return new Promise((resolve) => {
    const timer = setInterval(async () => {
      const res = await fetchDataProcess({ folderIds: id })
      const data = res.data.dataProcessList.find((item: any) => item.id === id)
      console.log(
        '状态:',
        dataStatusList.find((item: any) => item.value === data.status)?.desc
      )
      if (data?.status === published) {
        clearInterval(timer)
        resolve(true)
      } else if (errorCodes.includes(data.status)) {
        clearInterval(timer)
        resolve(false)
      }
    }, 2000)
  })
}

下载文件

ts
/**下载文件 */
async function downBlobFileWithHeaderName(url: any, params: any) {
  try {
    const response = await request({
      url: url,
      method: 'get',
      responseType: 'blob',
      returnOriginResponse: true, //handleResponse中返回原始的响应
      params
    } as any)
    const contentDisposition = response.headers['content-disposition']
    const fileName = decodeURIComponent(
      contentDisposition.split('filename=')[1]
    )
    handleBlobFile(response.data, fileName)
  } catch (error) {
    console.error('下载失败', error)
  }
}
ts
function handleBlobFile(response: any, fileName: string) {
  // 处理返回的文件流
  const blob = response
  if (blob && blob.size === 0) {
    console.error('文件流为空')
    return
  }
  const link = document.createElement('a')

  // 兼容一下 入参不是 File Blob 类型情况
  var binaryData = [] as any
  binaryData.push(response)
  link.href = window.URL.createObjectURL(new Blob(binaryData))
  link.download = fileName
  document.body.appendChild(link)
  link.click()
  window.setTimeout(function () {
    // @ts-ignore
    URL.revokeObjectURL(blob)
    document.body.removeChild(link)
  }, 0)
}
ts
/**调用地图服务 */
async function callMapService(id: string) {
  //调用地图服务
  downBlobFileWithHeaderName(`/admin/tx/data/downloadIndex`, {
    folderId: id //文件id
  })
}
ts
/**下载素材 */
function downLoadFile(id: string, projectId?: string) {
  const { userId } = CONSTANTS.USER_INFO.sysUser
  window.open(
    `${CONSTANTS.API_URL}/admin/tx/folders/getFile?id=${id}&projectId=${
      projectId ?? ''
    }&userId=${userId}`,
    '_blank',
    ''
  )
}

Released under the MIT License.