童鞋,[HttpClient发送文件] 的技术实践请查收
1.荒腔走板
前几天有个童鞋在群里面问:怎么使用HttpClient发送文件?
之前我写了一个ABP上传文件,主要体现的是服务端,上传文件的动作是由前端小姐姐完成的, 我还真没有用HttpClient编程方式发送过文件。
不过想来,Web协议都是一样的,类比前端发送文件,httpclient按照multipart/form-data
媒体类型应该也是可以发送的。
花一个钟头阅读了MDN Web协议,写成了HttpClient发送文件的实例, 看官自取。
2.头脑风暴
我们跟随常见的表单上传文件思路来实现HttpClinet上传文件。
multipart/form-data是一种多部分的文档格式,每部分由边界线(一个由'--'开始的字符串)划分, 也是一种请求的媒体类型MIME
如下面的表单, 有三个待提交input表单字段
<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
类型。
3.照葫芦画瓢
以上就是常规的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 服务端
上传文件的代码在 《》一文已经体现,本次截取接收文件上传的核心代码
[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; }
码甲哥从不打诳语,启动客户端/服务端
3.3 授人以渔
成熟的技术必须有成熟的调试和监测手段!
成熟的技术必须有成熟的调试和监测手段!
成熟的技术必须有成熟的调试和监测手段!
每当做web开发出现阻塞的时候,我就掏出web利器: Fiddler。
跟着Fiddler去倒腾吧。
总结
- 对常规html表单上传文件,做源码级分析。
- 根据分析结果,HttpClient使用同样的姿势发送文件: 使用
multipart/form-data
(多部分表单媒体类型)发起上传请求。
本文来自博客园,作者:{有态度的马甲},转载请注明原文链接:https://www.cnblogs.com/JulianHuang/p/15697845.html
欢迎关注我的原创技术、职场公众号, 加好友谈天说地,一起进化
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2019-12-17 MongoDB 快速扫盲贴