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

相关文章

2. c#从不同cs的文件调用函数

1.文件目录如下: 2. Program.cs文件的主函数如下 using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace datasAnalysis{internal static

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

Spring MVC 图片上传

引入需要的包 <dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-

【LabVIEW学习篇 - 21】:DLL与API的调用

文章目录 DLL与API调用DLLAPIDLL的调用 DLL与API调用 LabVIEW虽然已经足够强大,但不同的语言在不同领域都有着自己的优势,为了强强联合,LabVIEW提供了强大的外部程序接口能力,包括DLL、CIN(C语言接口)、ActiveX、.NET、MATLAB等等。通过DLL可以使用户很方便地调用C、C++、C#、VB等编程语言写的程序以及windows自带的大

如何更优雅地对接第三方API

如何更优雅地对接第三方API 本文所有示例完整代码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/third 我们在日常开发过程中,有不少场景会对接第三方的API,例如第三方账号登录,第三方服务等等。第三方服务会提供API或者SDK,我依稀记得早些年Maven还没那么广泛使用,通常要对接第三方

C# dateTimePicker 显示年月日,时分秒

dateTimePicker默认只显示日期,如果需要显示年月日,时分秒,只需要以下两步: 1.dateTimePicker1.Format = DateTimePickerFormat.Time 2.dateTimePicker1.CustomFormat = yyyy-MM-dd HH:mm:ss Tips:  a. dateTimePicker1.ShowUpDown = t

C#关闭指定时间段的Excel进程的方法

private DateTime beforeTime;            //Excel启动之前时间          private DateTime afterTime;               //Excel启动之后时间          //举例          beforeTime = DateTime.Now;          Excel.Applicat

C# 防止按钮botton重复“点击”的方法

在使用C#的按钮控件的时候,经常我们想如果出现了多次点击的时候只让其在执行的时候只响应一次。这个时候很多人可能会想到使用Enable=false, 但是实际情况是还是会被多次触发,因为C#采用的是消息队列机制,这个时候我们只需要在Enable = true 之前加一句 Application.DoEvents();就能达到防止重复点击的问题。 private void btnGenerateSh