找回密码
 会员注册
查看: 190|回复: 0

ASP.NET Web api接收multipart/form-data文件,解析MultipartFormDataStrea

[复制链接]

1389

主题

5

回帖

496万

积分

管理员

积分
4962990
发表于 2024-2-29 08:23:42 | 显示全部楼层 |阅读模式

在ASP.NET Web api 中,接收multipart/form-data文件,我们可以使用MultipartFormDataStreamProvider来保存图片

  1. [HttpPost,Route("api/Job/newJob")]
  2. public async Task<IHttpActionResult> PostNewJob()
  3. {
  4. string root = HttpContext.Current.Server.MapPath("~/img/workImg");//指定要将文件存入的服务器物理位置
  5. //继承MultipartFormDataStreamProvider类
  6. var provider =new MultipartFormDataStreamProvider(root);
  7. try
  8. { //执行完这条之后,文件便保存了
  9. await Request.Content.ReadAsMultipartAsync(provider);
  10. }
  11. catch (IOException innException)
  12. { //下面可以不用看,主要是上面的代码
  13. //检测是否是MyMultipartFormDataStream的 GetLocalFileName方法发生异常
  14. if (innException.InnerException.InnerException.InnerException == null)
  15. {
  16. return Json(new { code = "500", Message = "文件写入错误" });
  17. }
  18. return Json(new { code = "500", Message = innException.InnerException.InnerException.InnerException.Message
  19. }
  20. }
复制代码

在这里插入图片描述

这里我们可以看到,使用MultipartFormDataStreamProvider默认保存的文件名的格式是BodyPart加上一串数字字母组合而成,如果我们想要自定义文件名的话,我们可以继承MultipartFormDataStreamProvider类并重写GetLocalFileName方法

  1. public class MyMultipartFormDataStreamProvider:MultipartFormDataStreamProvider
  2. {
  3. public MyMultipartFormDataStreamProvider(string path) : base(path) { }
  4. public override string GetLocalFileName(HttpContentHeaders headers)
  5. {
  6. //这里获取上传的文件名
  7. string Name = headers.ContentDisposition.FileName.Replace(""", string.Empty);
  8. //这里做了一个判断,只有jpg,png,gif为后缀的,才给保存,否则抛出一个错误(写这个判断的原因是因为需求原因)
  9. if (Name.EndsWith(".jpg", StringComparison.CurrentCultureIgnoreCase) ||
  10. Name.EndsWith(".png", StringComparison.CurrentCultureIgnoreCase) ||
  11. Name.EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase))
  12. {
  13. //以ContentDisposition的哈希值加上传的名字作为文件名
  14. return $"{headers.ContentDisposition.GetHashCode()}_{Name}";
  15. }
  16. throw new InvalidOperationException("上传格式错误");
  17. }
  18. }
复制代码

在这里插入图片描述

这里我们可以看到文件的文件名被改写成我们想要的名字了,到这里,出现两个疑问。
1.为什么重写GetLocalFileName方法就可以重写文件名呢?

2.文件是怎么保存的呢?
我们先来讲解第二个问题,因为第二个问题讲解完了 第一个问题就知道答案了


文件是怎么保存的呢?
  1. await Request.Content.ReadAsMultipartAsync(provider);
复制代码

文件能够自动保存的秘密就在这个ReadAsMultipartAsync这个方法里面,下面我们来看看它的源代码是怎么样的。

在这里插入图片描述

在这里插入图片描述

1.首先ReadAsMultipartAsync中获取了请求中的流,然后存储在MultipartAsyncContext里面,然后把MultipartAsyncContext作为参数调用了MultipartReadAsync方法。

在这里插入图片描述

2.在MultipartReadAsync方法中,这里我也不知道这个方法做了什么,但是我们看到了WriteSegment方法,看起来比较可疑,看看这个方法是什么来的。

在这里插入图片描述

3.在WriteSegment方法中,我们发现调用了GetOutputStream()方法 ,细心的小伙伴可能会发现,GetOutputStream调用了MultipartFormDataStreamProvider的GetStream方法

在这里插入图片描述

4.GetStream方法中,我们可以通过源代码发现,这个方法的目的是为了获取被File.Create创造的文件的流,而想要流,就要有文件的路径,这里它调用了GetLocalFileName方法,这里就解答了为什么重写GetLocalFileName方法会改写文件名。
WriteSegment方法获取了文件的流之后,使用WriteAsync方法向流里面写东西进去,写入的东西我猜是上传文件的数据。

下面我们来简单回答下我们提出的两个问题:
2.文件是怎么保存的呢?
调用ReadAsMultipartAsync的过程中,它首先根据文件路径 (MultipartFormDataStreamProvider提供) 创造一个文件并获取这个文件的流,然后在把数据写进流里面保存,这样,一个文件就保存完成了。

1.为什么重写GetLocalFileName方法就可以重写文件名呢?
因为在保存文件的过程中需要获取文件的流,而获取文件的流需要文件的路径,文件的路径是由MultipartFormDataStreamProviderGetStreamGetLocalFileName

到这里,文件的保存过程就讲完了,以上是我的观点,如果有什么说错的地方,别喷O(∩_∩)O,欢迎留言。


来源:https://blog.csdn.net/MDZZ666/article/details/89202548
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?会员注册

×
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 13:12 , Processed in 0.491652 second(s), 27 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表