ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

GeoServer 一键发布 Raster 数据服务(分片上传、GDAL)

2021-10-09 14:01:49  阅读:225  来源: 互联网

标签:数据服务 Raster const string S4 file GeoServer var 上传


项目中需要上传影像数据并能查看。于是想到的思路是:上传后发布为 GeoServer 服务,再加载地图服务查看。

要实现该功能用到的技术还是不少的,下面就分别介绍下。

一、大文件上传

因为影像文件一般比较大,上传的时候就遇到了问题。

.net core 官网给出的是用流的方式上传,测试了没有成功。

最后选择的是分片上传实现的。

.net core + Vue 分片上传代码如下:

前端代码:

    customRequest() {
      const url = BASE_API + '/multipartupload'
      const createGuid = function() {
        function S4() {
          return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
        }
        return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4())
      }
      // element 组件的 upload 绑定的文件,这里改变为正在上传状态,下面设置的上传百分比才有效
      this.uploadFile[0].status = 'uploading'
      this.fileUpload(url, this.uploadFile[0].raw, 0, createGuid())
    },
    // 上传文件,递归调用
    fileUpload(uploadUrl, file, chunk, guid) {
      // const file = option.file
      // 每次上传文件的大小 5M
      const chunkSize = 1024 * 1024 * 5
      // 最大上传大小  默认1000M
      const maxSize = 1024 * 1024 * 1000
      const maxChunk = Math.ceil((file.size / chunkSize))
      const formData = new FormData()
      // 将文件进行分段
      const fileSize = file.size
      if (fileSize > maxSize) {
        this.$message.error('文件大小不能超过1000M')
        return
      }

      // 当前上传进度
      const currentPercent = parseInt((chunk / maxChunk) * 100)
      // option.onProgress({ percent: currentPercent })
      formData.append('file', file.slice(chunk * chunkSize, (chunk + 1) * chunkSize))
      formData.append('name', file.name)
      formData.append('chunk', chunk)
      formData.append('maxChunk', maxChunk)
      formData.append('guid', guid)
      this.$request.post(uploadUrl, formData).then(result => {
        if (result.code === 0) {
          // upload 设置上传进度
          this.uploadFile[0].percentage = currentPercent
          if (result.message === '上传中') {
            this.fileUpload(uploadUrl, file, ++chunk, guid)
          } else {
            this.$message.success('文件上传成功')
            this.uploadFile[0].status = 'success'
          }
        } else {
          this.$message.error(result.message)
        }
      })
    }

后端代码:

        public async Task<ResponseData> MultipartUpload(MultipartUploadDTO multipartUpload)
        {
            string _targetFilePath = @"D:\Data\UploadFiles";
            //临时保存分块的目录
            var dir = Path.Combine(_targetFilePath, multipartUpload.Guid);
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            //分块文件名为索引名,更严谨一些可以加上是否存在的判断,防止多线程时并发冲突
            var filePath = Path.Combine(dir, multipartUpload.Chunk.ToString());
            //获取文件扩展名
            //var extension = file.FileName.Substring(file.FileName.LastIndexOf(".") + 1, (file.FileName.Length - file.FileName.LastIndexOf(".") - 1));
            var filePathWithFileName = string.Concat(filePath, multipartUpload.Name);
            using (var stream = new FileStream(filePathWithFileName, FileMode.Create))
            {
                await multipartUpload.Flie.CopyToAsync(stream);
            }

            //如果是最后一个分块, 则合并文件
            string message = "上传中";
            string path = "";
            if (multipartUpload.Chunk == multipartUpload.MaxChunk - 1)
            {
                path = await MergeFileAsync(multipartUpload.Name, multipartUpload.Guid, _targetFilePath);
                message = "上传完成!";
            }
            return new ResponseData() { Code = 0, Message = message, Data = path };
        }

        /// <summary>
        /// 合并分片的文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="guid"></param>
        /// <returns></returns>
        private async Task<string> MergeFileAsync(string fileName, string guid,string _targetFilePath)
        {
            //临时文件夹
            string dir = Path.Combine(_targetFilePath, guid);
            //最终的文件名
            string finalName = $"{DateTime.Now:yyyyMMddHHmmssff}{fileName}";
            string finalPath = Path.Combine(_targetFilePath, finalName);

            //获得下面的所有文件
            var files = Directory.GetFiles(dir);
            using (var fs = new FileStream(finalPath, FileMode.Create))
            {
                //排一下序,保证从0-N Write
                var fileParts = files.OrderBy(x => x.Length).ThenBy(x => x);
                foreach (var part in fileParts)
                {
                    var bytes = await File.ReadAllBytesAsync(part);
                    await fs.WriteAsync(bytes, 0, bytes.Length);
                    bytes = null;
                    //删除分块
                    File.Delete(part);
                }
                await fs.FlushAsync();
                fs.Close();
                //删除临时文件夹和分片文件
                Directory.Delete(dir);
            }

            return finalName;
        }

主要思路是:把同一个文件分成指定大小字节(byte)分片上传,全部上传后再合并为同一个文件。

二、.NET Core 调用 GDAL 

要发布 Raster 服务,需要知道文件的一些基本信息:坐标系、坐标范围等信息。

GDAL 可以很方便操作 GIS 数据,GDAL 官方给的类库是 C++ 版本。

要调用的话可以自己下载对应的 dll 进行调用。

在这里查找到了一个已经封装好的类库,在这里直接调用。

MaxRev.Gdal.Core

使用还需要注意几点:

1、需要的对应运行时:MaxRev.Gdal.LinuxRuntime.Minimal、MaxRev.Gdal.WindowsRuntime.Minimal (根据自己的平台来选择)

2、使用前初始化配置:GdalBase.ConfigureAll()

在项目中使用的主要功能有:

// 读取数据
Dataset dataset = Gdal.Open(tiffFile, Access.GA_ReadOnly);
double[] tr = new double[6];
// 获取 transform 数据
dataset.GetGeoTransform(tr);
// 获取 x、y 像素数
int xSize = dataset.RasterXSize;
int ySize = dataset.RasterYSize;
// 获取坐标信息
string projection = dataset.GetProjection();

三、GeoServer REST API 使用

上面的准备工作都已经完成,后面就是要发布对应的 Raster 服务了。

GeoServer 提供了全部功能的 REST API 供调用。

官方 REST 文档

点进每一个里面都是 Swagger 文档

只要具备后端经验的,查看该文档毫无压力。

标签:数据服务,Raster,const,string,S4,file,GeoServer,var,上传
来源: https://www.cnblogs.com/zhurong/p/15384912.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有