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#实现MQTT通信实战

《基于C#实现MQTT通信实战》MQTT消息队列遥测传输,在物联网领域应用的很广泛,它是基于Publish/Subscribe模式,具有简单易用,支持QoS,传输效率高的特点,下面我们就来看看C#实现... 目录1、连接主机2、订阅消息3、发布消息MQTT(Message Queueing Telemetr

C#特性(Attributes)和反射(Reflection)详解

《C#特性(Attributes)和反射(Reflection)详解》:本文主要介绍C#特性(Attributes)和反射(Reflection),具有很好的参考价值,希望对大家有所帮助,如有错误... 目录特性特性的定义概念目的反射定义概念目的反射的主要功能包括使用反射的基本步骤特性和反射的关系总结特性

python通过curl实现访问deepseek的API

《python通过curl实现访问deepseek的API》这篇文章主要为大家详细介绍了python如何通过curl实现访问deepseek的API,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编... API申请和充值下面是deepeek的API网站https://platform.deepsee

C#实现查找并删除PDF中的空白页面

《C#实现查找并删除PDF中的空白页面》PDF文件中的空白页并不少见,因为它们有可能是作者有意留下的,也有可能是在处理文档时不小心添加的,下面我们来看看如何使用Spire.PDFfor.NET通过C#... 目录安装 Spire.PDF for .NETC# 查找并删除 PDF 文档中的空白页C# 添加与删

Java实现MinIO文件上传的加解密操作

《Java实现MinIO文件上传的加解密操作》在云存储场景中,数据安全是核心需求之一,MinIO作为高性能对象存储服务,支持通过客户端加密(CSE)在数据上传前完成加密,下面我们来看看如何通过Java... 目录一、背景与需求二、技术选型与原理1. 加密方案对比2. 核心算法选择三、完整代码实现1. 加密上

通过C#获取Excel单元格的数据类型的方法详解

《通过C#获取Excel单元格的数据类型的方法详解》在处理Excel文件时,了解单元格的数据类型有助于我们正确地解析和处理数据,本文将详细介绍如何使用FreeSpire.XLS来获取Excel单元格的... 目录引言环境配置6种常见数据类型C# 读取单元格数据类型引言在处理 Excel 文件时,了解单元格

Java对接Dify API接口的完整流程

《Java对接DifyAPI接口的完整流程》Dify是一款AI应用开发平台,提供多种自然语言处理能力,通过调用Dify开放API,开发者可以快速集成智能对话、文本生成等功能到自己的Java应用中,本... 目录Java对接Dify API接口完整指南一、Dify API简介二、准备工作三、基础对接实现1.

C#实现高性能Excel百万数据导出优化实战指南

《C#实现高性能Excel百万数据导出优化实战指南》在日常工作中,Excel数据导出是一个常见的需求,然而,当数据量较大时,性能和内存问题往往会成为限制导出效率的瓶颈,下面我们看看C#如何结合EPPl... 目录一、技术方案核心对比二、各方案选型建议三、性能对比数据四、核心代码实现1. MiniExcel

在React聊天应用中实现图片上传功能

《在React聊天应用中实现图片上传功能》在现代聊天应用中,除了文字和表情,图片分享也是一个重要的功能,本文将详细介绍如何在基于React的聊天应用中实现图片上传和预览功能,感兴趣的小伙伴跟着小编一起... 目录技术栈实现步骤1. 消息组件改造2. 图片预览组件3. 聊天输入组件改造功能特点使用说明注意事项

一文详解如何在Vue3中封装API请求

《一文详解如何在Vue3中封装API请求》在现代前端开发中,API请求是不可避免的一部分,尤其是与后端交互时,下面我们来看看如何在Vue3项目中封装API请求,让你在实现功能时更加高效吧... 目录为什么要封装API请求1. vue 3项目结构2. 安装axIOS3. 创建API封装模块4. 封装API请求