童鞋,[HttpClient发送文件的技术实践]请查收

717cd7ae3ef575fc30d29c0cab1e6a68.gif

    昨天有童鞋在群里面问:怎么使用HttpClient发送文件?

01

荒腔走板

      之前我写了一个《ABP小试牛刀之上传文件》,主要体现的是服务端,上传文件的动作是由前端小姐姐完成的, 我还真没有用HttpClient编程方式发送过文件。

不过HttpClient的动作遵守Web协议,盲猜httpclient按照前端multipart/form-data媒体类型发送文件应该也是可行的。

花一个小时阅读了MDN Web协议,写就了HttpClient发送文件的实例, 看官自取。

02

头脑风暴

      我们跟随常见的表单上传文件思路来实现HttpClinet上传文件。

multipart/form-data是一种由多部分表单域值组成的媒体类型,每部分由边界线(一个由'--'开始的字符串)划分。

如下面的表单, 有三个待提交input表单字段

cc9be15c6e37b50295f22e135fa80f68.png


<form action="http://localhost:8000/" method="post" enctype="multipart/form-data"><input type="text" name="myTextField"><input type="checkbox" name="myCheckBox">Check</input><input type="file" name="myFile"><button>Send the file</button>
</form>

选中文件,点击[Send the file]按钮,提交表单,会发出如下请求

请观察由boundary划分的每个表单域和值, 其中myFile是一个文件表单域, 这个文件域需要单独指定Content-Type类型。

b5a0a9c63998477f16136bb3add1f38b.png

03

照葫芦画瓢

       以上就是常规的Html表单上传文件的协议分析,回到本文主题, 这次会使用HttpClient编码形式发送只含有一个文件表单域的请求 (依旧利用的multipart/form-data媒体类型), 这也是下文的实现思路。

下面是httpclient向localhost:5000/upload地址上传文件, 服务器返回图片的base64编码字符串。

3.1 客户端

using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApp3
{class Program{static readonly HttpClient client = new HttpClient();static async Task Main(){try{byte[] bytes;using (var bodyStream = new FileStream(@"D:\001.png", FileMode.Open)){using var m = new MemoryStream();await bodyStream.CopyToAsync(m);bytes = m.ToArray();}// 1. 准备文件表单域和值var byteArrayContent = new ByteArrayContent(bytes);byteArrayContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");// 2.  向MultipartFormDataContent插入准备好的文件表单域值, 注意MultipartFormDataContent是一个集合类型。var response = await client.PostAsync("http://localhost:5000/upload", new MultipartFormDataContent(Guid.NewGuid().ToString()){{ byteArrayContent, "uploadedFile", "\"001ggg.png\""}});response.EnsureSuccessStatusCode();var responseBody = await response.Content.ReadAsStringAsync();Console.WriteLine(responseBody);}catch (HttpRequestException e){Console.WriteLine("\nException Caught!");Console.WriteLine("Message :{0} ", e.Message);}}}
}

•请注意,我使用一个随机的GUID做为每个表单域的划分边界,这里我向MultipartFormDataContent只插入了一个文件表单阈值,这样就做到了HttpClient发送文件。•文件表单域值:  { byteArrayContent, "uploadedFile", "\"001ggg.png\""} 中的参数2: 字段名称很重要,要与下面服务端的参数名匹配。

3.2 服务端

上传文件的代码在《ABP小试牛刀之上传文件》一文已经体现,本次截取接收文件上传的核心代码

[Consumes("multipart/form-data")]
[Route("upload")]
[ProducesResponseType(typeof(Guid), 200)]
[HttpPost]
public async Task<string> UploadAsync(IFormFile uploadedFile)
{var formFileName = uploadedFile.FileName;if (!new[] { ".png", ".jpg", ".bmp" }.Any((item) => formFileName.EndsWith(item))){throw new NotImplementedException("您上传的文件格式必须为png、jpg、bmp中的一种");}byte[] bytes;using (var bodyStream = uploadedFile.OpenReadStream()){using (var m = new MemoryStream()){await bodyStream.CopyToAsync(m);bytes = m.ToArray();}}var base64 = Convert.ToBase64String(bytes);return base64;
}

码甲哥从不打诳语,启动客户端/服务端

3224745efebce83468285b7bb9d13d96.png

3.3 授人以渔

成熟的技术必须有成熟的调试和监测手段!

成熟的技术必须有成熟的调试和监测手段!

成熟的技术必须有成熟的调试和监测手段!

8f8b50c8db8f77b9aab7a67cf8c1761b.gif

每当做web开发出现阻塞的时候,我就掏出web利器Fiddler,跟着Fiddler去策马奔腾吧。

60f602a0b3de3bf503da7e94e7ceecb1.png

# 全文总结

1.对常规html表单上传文件的功能,做协议级分析。2.根据分析结果,HttpClient使用同样的姿势发送文件: 使用multipart/form-data(多部分表单媒体类型)发起上传请求。

[1] 媒体类型MIME: https://developer.mozilla.org/zhCN/docs/Web/HTTP/Basics_of_HTTP/MIME_types

我是有态度的马甲,不追热点,原创输出 # 八股文 # 硬核干货 # 职场心得 #,欢迎关注。

点分享

点点赞

点在看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/294033.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android之Camera介绍

Android Camera 使用小结 Android手机关于Camera的使用&#xff0c;一是拍照&#xff0c;二是摄像&#xff0c;由于Android提供了强大的组件功能&#xff0c;为此对于在Android手机系统上进行Camera的开发&#xff0c;我们可以使用两类方法&#xff1a;一是借助Intent和MediaSt…

elasticsearch2.2之javaApi

2019独角兽企业重金招聘Python工程师标准>>> 前言&#xff1a;elasticsearch虽然自带rest接口&#xff0c;但是在真正使用过程中可能更多的是通过不同编程语言的客户端进行交互。 因为代码里有或多或少的注释&#xff0c;所以直接贴代码&#xff1a; package elasti…

My SQL 学习笔记二

本文主要记录这两天遇到的问题&#xff1a; 1.sql脚本文件存在自己的目录下&#xff0c;例如在F盘&#xff0c;通过命令&#xff1a;mysql> source F:/filename.sql 会弹出Failed to open file "F:/filename.sql" error:2 错误 这个错误一般是Mysql没有权限访问文…

《程序员的职业素养》读书笔记

书籍地址&#xff1a;http://book.douban.com/subject/11614538/ 一句话点评该书&#xff1a;Bob大叔的职业生涯经验总结&#xff0c;现身说法&#xff0c;可信可敬&#xff01; &#xff08;一&#xff09;专业主义 &#xff08;1&#xff09;“专业主义”就意味着担当责…

html 转义反斜杠字符串,JS中处理单个反斜杠(即转义字符的处理)

问题来源&#xff1a;在表单的标签中对输入的字符串进行大写转换。一不小心输入了反斜杠 \如下图所示&#xff1a;输入 chn\ 的时候&#xff0c;在 IE8 下弹出一个js错误。(在实际的项目的表单元素中遇到了&#xff0c;单独这样拿出来测试的时候又不弹出错误。也很是焦灼)索…

Android之SurfaceView简介(一)

1. SurfaceView介绍 通常情况程序的View和用户响应都是在同一个线程中处理的&#xff0c;这也是为什么处理长时间事件&#xff08;例如访问网络&#xff09;需要放到另外的线程中去&#xff08;防止阻塞当前UI线程的操作和绘制&#xff09;。但是在其他线程中却不能修改UI元素&…

C# 值得永久收藏的WPF项目实战(经典)

01—简介之前也写过好多篇CM框架相关的项目实战文章&#xff0c;比如&#xff1a;C# WPF框架Caliburn.Micro快速搭建C# WPF框架Caliburn.Micro入门实例1C# WPF MVVM项目实战(进阶①)C# WPF MVVM项目实战(进阶②)C# WPF MVVM模式下在主窗体显示子窗体并获取结果C# WPF Caliburn.…

InfoQ十周年:不忘初心,继续前行

我们都知道&#xff1a;软件正在改变世界&#xff0c;也已经看到了在加快这种变化时&#xff0c;于软件世界中我们的影响力。在这种热情下&#xff0c;10年前我们带着一些不寻常的信念与情怀创建了InfoQ&#xff1a;\\\\t我们相信&#xff1a;这个社区需要的内容是开发者所撰写…

eclipse_中的注释_快捷键

eclipse 中的注释 快捷键 把要注释的代码选中&#xff0c;按CtrlShift/ /* */ 形式的 ctrl/ //形式的 取消代码注释&#xff1a; 把要注释的代码选中&#xff0c;按CtrlShift\ /* */ 形式的 ctrl/ //形式的 (1)CtrlSpace 说明:内容助理。提供对方法,变量,参数,j…

html自动填充高度,html元素如何仅使用css填充剩余屏幕高度的100%?

html元素如何仅使用css填充剩余屏幕高度的100&#xff05;&#xff1f;我有一个标题元素和一个内容元素&#xff1a;#header#content我希望标题具有固定的高度&#xff0c;并且内容可以填满屏幕上可用的所有剩余高度&#xff0c;使用overflow-y: scroll;。这可能没有Javascript…

Android之bitmap压缩的几种方法的解读

转载&#xff1a;http://blog.csdn.net/chzphoenix/article/details/30242315?utm_sourcetuicool&utm_mediumreferral 最近在研究微信的sdk&#xff0c;在缩略图这遇到了一点问题。 微信的缩略图要求是不大于32k&#xff0c;这就需要对我的图片进行压缩。试了几种方法&a…

如何通过 C# kill 指定进程?

咨询区 robr我用代码动态的打开了一个 IE 进程&#xff0c;参考如下代码&#xff1a;static void Main(string[] args){ProcessStartInfo startInfo new ProcessStartInfo("iexplore.exe");startInfo.WindowStyle ProcessWindowStyle.Hidden;startInfo.Arguments …

[转]面向接口编程详解(一)——思想基础

我想&#xff0c;对于各位使用面向对象编程语言的程序员来说&#xff0c;“接口”这个名词一定不陌生&#xff0c;但是不知各位有没有这样的疑惑&#xff1a;接口有什么用途&#xff1f;它和抽象类有什么区别&#xff1f;能不能用抽象类代替接口呢&#xff1f;而且&#xff0c;…

bootstrap模态框

bootsrtap模态框不可叠加使用&#xff0c;点击提交时需要确认&#xff0c;暂时未解决转载于:https://www.cnblogs.com/witchgogogo/p/5550338.html

Oracle 在 多个Virtualbox 虚拟机间 跨不同物理宿主机进行通信

因为单位网络管理的原因&#xff0c;不太方便使用 Virtualbox 的Bridge Adapter 模式&#xff0c;故此欲采用NAT模式&#xff0c;不对外不暴露虚拟机IP。 但是此时会有一个问题&#xff1a;采用NAT模式后&#xff0c;在通常情况下&#xff0c; 从外面看&#xff0c;或者从物理机…

Android之解决在非Activity中使用startActivity

今天遇到一个问题就是&#xff0c;如何在非activity里面使用startActivity(); 解决办法如下、 需要我们有context intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent);

亚马逊 html代码转换,亚马逊七种产品描述常用HTML代码,文字颜色代码让Listing更出彩...

排版风格和排版水平对于亚马逊Listing的运营至关重要。虽说亚马逊以产品为王&#xff0c;但如果消费者打开的是一篇毫无美感的排版&#xff0c;视觉体验不舒服&#xff0c;获取不到吸引他的卖点&#xff0c;转化率将大大降低&#xff01;没使用HTML代码的卖家&#xff0c;产品描…

如何将自定义的 Delegate 转成 Func 委托?

咨询区 AndreyAkinshin场景是这样的&#xff0c;我自定义了一个 SomeDelegate 委托&#xff0c;然后将 Inc 方法灌入到其中&#xff0c;同时我也将 Inc 赋值给了 Func<int,int> 委托&#xff0c;参考代码如下&#xff1a;class Program{static void Main(string[] args){…