C# HttpWebRequest 上传文件 (调用ArcGIS Rest API上传SOE文件)

2023-11-06 00:30

本文主要是介绍C# HttpWebRequest 上传文件 (调用ArcGIS Rest API上传SOE文件),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

缘起

想做一个SOE自动上传的小工具,查了查相关的ArcGIS Rest API,使用C#中的HttpWebRequet实现,k看GitHub上别人用Python实现的很简单,自己用C#搞了一天了没搞明白,记录一下采坑的过程。

相关资料

  1. ArcGIS Rest API Upload SOE:传送门
  2. C# Upload File:参考链接1、参考链接2、
  3. HttpClient实现方法:参考链接

PostMan测试

使用PostMan测试Form-data,参考链接
在这里插入图片描述

代码实现

  • HttpWebRequest

    private bool UploadSoe(string userName, string password, string soeFilePath, string ip = "localhost", string port = "6080")
    {bool bIsSuccess = false;//构造请求参数string token = GetToken(userName, password, ip, port);string boundary = CreateFormDataBoundary();byte[] postDataBytes = null;using (var postStream = new MemoryStream()){//写入表单参数string formDataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n";string fromData1 = string.Format(formDataTemplate, boundary, "f", "json");var dataFormdataBytes1 = Encoding.UTF8.GetBytes(fromData1);string formData2 = string.Format(formDataTemplate, boundary, "token", token);var dataFormdataBytes2 = Encoding.UTF8.GetBytes(formData2);//写入文件头部信息string fileFormdataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n";string soeFileName = System.IO.Path.GetFileName(soeFilePath);string fileHeader = string.Format(fileFormdataTemplate, boundary, "itemFile", soeFileName, "application/octet-stream");byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(fileHeader);//写入文件流byte[] fileBytes = null;using (FileStream fs = new FileStream(soeFilePath, FileMode.Open)){fileBytes = new byte[fs.Length];fs.Read(fileBytes, 0, fileBytes.Length);fs.Close();}//写入结尾string sEndBoundary = "\r\n--" + boundary + "--\r\n";var endBoundaryBytes = Encoding.UTF8.GetBytes(sEndBoundary);postStream.Write(dataFormdataBytes1, 0, dataFormdataBytes1.Length);postStream.Write(dataFormdataBytes2, 0, dataFormdataBytes2.Length);postStream.Write(headerbytes, 0, headerbytes.Length);postStream.Write(fileBytes, 0, fileBytes.Length);postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);postStream.Position = 0;postDataBytes = new byte[postStream.Length];postStream.Read(postDataBytes, 0, postDataBytes.Length);postStream.Close(); }//创建Httphelper对象HttpHelper http = new HttpHelper();//创建Httphelper参数对象HttpItem item = new HttpItem(){URL = string.Format("http://{0}:{1}/arcgis/admin/uploads/upload", ip, port),Method = "POST",ContentType = string.Format("multipart/form-data; boundary={0}", boundary),PostDataType = Sys.PostDataType.Byte,PostdataByte = postDataBytes};//请求的返回值对象HttpResult result = http.GetHtml(item);if (result.StatusCode == System.Net.HttpStatusCode.OK){string html = result.Html;var jsonObj = JsonHelper.GetDynamicObjFromString(html);if (jsonObj.status.ToString() == "success"){bIsSuccess = true;}}return bIsSuccess;
    }private static string CreateFormDataBoundary()
    {return "----" + DateTime.Now.Ticks.ToString("x");
    }private string GetToken(string userName, string password, string ip = "localhost", string port = "6080")
    {//创建Httphelper对象HttpHelper http = new HttpHelper();//创建Httphelper参数对象HttpItem item = new HttpItem(){URL = string.Format("http://{0}:{1}/arcgis/admin/generateToken", ip, port),//URL     必需项    Method = "post",//URL     可选项 默认为Get   ContentType = "application/x-www-form-urlencoded",//返回类型    可选项有默认值Postdata = string.Format("username={0}&password={1}&client=requestip&expiration=90&f=json", userName, password),//Post要发送的数据};//请求的返回值对象HttpResult result = http.GetHtml(item);//从苏飞论坛或者Github获取,也可以自己用HttpWebRequest//获取请请求的Htmlstring html = result.Html;//获取请求的Cookievar jsonObj = JsonHelper.GetDynamicObjFromString(html);var token = jsonObj.token;return token.ToString();
    }
    
  • HttpClient

    private async void UploadSoe1(string userName, string password, string soeFilePath, string ip = "localhost", string port = "6080")
    {string token = GetToken(userName, password, ip, port);string soeFileName = Path.GetFileName(soeFilePath);using (FileStream stream = new FileStream(soeFilePath, FileMode.Open))using (HttpClient client = new HttpClient()){MultipartFormDataContent content = new MultipartFormDataContent();content.Add(new StringContent("pjson"), "f");content.Add(new StringContent(token), "token");content.Add(new StreamContent(stream){Headers ={ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream")}}, "itemFile", soeFileName);string url = string.Format("http://{0}:{1}/arcgis/admin/uploads/upload", ip, port);var response = await client.PostAsync(url, content);string resultContent = await response.Content.ReadAsStringAsync();}}
    

采坑小记

使用HttpWebRequest时需要自行构造body,这块相比HttpClient麻烦一点,这块要注意构造请求体是字符串的顺序,依次往requestStream中写入

  1. 构造boundary信息

    private static string CreateFormDataBoundary()
    {return "----" + DateTime.Now.Ticks.ToString("x");
    }
    
  2. 构造请求参数的相关信息

    string formDataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n";
    string fromData1 = string.Format(formDataTemplate, boundary, "f", "json");
    var dataFormdataBytes1 = Encoding.UTF8.GetBytes(fromData1);
    
  3. 构造上传文件的相关信息

    string fileFormdataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n";
    string soeFileName = System.IO.Path.GetFileName(soeFilePath);
    string fileHeader = string.Format(fileFormdataTemplate, boundary, "itemFile", soeFileName, "application/octet-stream");	
    byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(fileHeader);
    
  4. 添加换行

    byte[] bytes = Encoding.UTF8.GetBytes("\r\n");
    
  5. 添加结尾信息

    string sEndBoundary = "--" + boundary + "--\r\n";
    var endBoundaryBytes = Encoding.UTF8.GetBytes(sEndBoundary);
    

最后依次写入:

  Stream requestStream = request.GetRequestStream();requestStream.Write(dataFormdataBytes1, 0, dataFormdataBytes1.Length);requestStream.Write(dataFormdataBytes2, 0, dataFormdataBytes2.Length);//这块我有两个参数,没有封装函数,直接重复代码写了两遍requestStream.Write(headerbytes, 0, headerbytes.Length);requestStream.Write(fileBytes, 0, fileBytes.Length);byte[] bytes = Encoding.UTF8.GetBytes("\r\n");requestStream.Write(bytes, 0, bytes.Length);requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);

总结

如果对.Net Framework的版本没有要求的话(可以使用4.5及以上版本)建议使用HttpClient实现,毕竟HTTPWebRequest是很久之前的类,调用起来构造比较麻烦。

这篇关于C# HttpWebRequest 上传文件 (调用ArcGIS Rest API上传SOE文件)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/353427

相关文章

一文解析C#中的StringSplitOptions枚举

《一文解析C#中的StringSplitOptions枚举》StringSplitOptions是C#中的一个枚举类型,用于控制string.Split()方法分割字符串时的行为,核心作用是处理分割后... 目录C#的StringSplitOptions枚举1.StringSplitOptions枚举的常用

C#自动化实现检测并删除PDF文件中的空白页面

《C#自动化实现检测并删除PDF文件中的空白页面》PDF文档在日常工作和生活中扮演着重要的角色,本文将深入探讨如何使用C#编程语言,结合强大的PDF处理库,自动化地检测并删除PDF文件中的空白页面,感... 目录理解PDF空白页的定义与挑战引入Spire.PDF for .NET库核心实现:检测并删除空白页

C#利用Free Spire.XLS for .NET复制Excel工作表

《C#利用FreeSpire.XLSfor.NET复制Excel工作表》在日常的.NET开发中,我们经常需要操作Excel文件,本文将详细介绍C#如何使用FreeSpire.XLSfor.NET... 目录1. 环境准备2. 核心功能3. android示例代码3.1 在同一工作簿内复制工作表3.2 在不同

C#中通过Response.Headers设置自定义参数的代码示例

《C#中通过Response.Headers设置自定义参数的代码示例》:本文主要介绍C#中通过Response.Headers设置自定义响应头的方法,涵盖基础添加、安全校验、生产实践及调试技巧,强... 目录一、基础设置方法1. 直接添加自定义头2. 批量设置模式二、高级配置技巧1. 安全校验机制2. 类型

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

C#使用iText获取PDF的trailer数据的代码示例

《C#使用iText获取PDF的trailer数据的代码示例》开发程序debug的时候,看到了PDF有个trailer数据,挺有意思,于是考虑用代码把它读出来,那么就用到我们常用的iText框架了,所... 目录引言iText 核心概念C# 代码示例步骤 1: 确保已安装 iText步骤 2: C# 代码程

C#实现高性能拍照与水印添加功能完整方案

《C#实现高性能拍照与水印添加功能完整方案》在工业检测、质量追溯等应用场景中,经常需要对产品进行拍照并添加相关信息水印,本文将详细介绍如何使用C#实现一个高性能的拍照和水印添加功能,包含完整的代码实现... 目录1. 概述2. 功能架构设计3. 核心代码实现python3.1 主拍照方法3.2 安全HBIT

C#实现SHP文件读取与地图显示的完整教程

《C#实现SHP文件读取与地图显示的完整教程》在地理信息系统(GIS)开发中,SHP文件是一种常见的矢量数据格式,本文将详细介绍如何使用C#读取SHP文件并实现地图显示功能,包括坐标转换、图形渲染、平... 目录概述功能特点核心代码解析1. 文件读取与初始化2. 坐标转换3. 图形绘制4. 地图交互功能缩放

使用Go调用第三方API的方法详解

《使用Go调用第三方API的方法详解》在现代应用开发中,调用第三方API是非常常见的场景,比如获取天气预报、翻译文本、发送短信等,Go作为一门高效并发的编程语言,拥有强大的标准库和丰富的第三方库,可以... 目录引言一、准备工作二、案例1:调用天气查询 API1. 注册并获取 API Key2. 代码实现3

C#使用SendMessage实现进程间通信的示例代码

《C#使用SendMessage实现进程间通信的示例代码》在软件开发中,进程间通信(IPC)是关键技术之一,C#通过调用WindowsAPI的SendMessage函数实现这一功能,本文将通过实例介绍... 目录第一章:SendMessage的底层原理揭秘第二章:构建跨进程通信桥梁2.1 定义通信协议2.2