0

0

ASP.NET WebAPi(selfhost)实现文件同步或异步上传

高洛峰

高洛峰

发布时间:2016-12-20 14:20:46

|

2557人浏览过

|

来源于php中文网

原创

前言
前面我们讲过利用angularjs上传到webapi中进行处理,同时我们在mvc系列中讲过文件上传,本文结合mvc+webapi来进行文件的同步或者异步上传,顺便回顾下css和js,mvc作为客户端,而webapi利用不依赖于iis的selfhost模式作为服务端来接收客户端的文件且其过程用ajax来实现,下面我们一起来看看。

同步上传

多余的话不用讲,我们直接看页面。

@if (ViewBag.Success != null) { } else if (ViewBag.Failed != null) { }
@using (Html.BeginForm("SyncUpload", "Home", FormMethod.Post, new { role = "form", enctype = "multipart/form-data", @style = "margin-top:50px;" })) {
}

上述我们直接上传后通过上传的状态来显示查看上传文件路径并访问,就是这么简单。下面我们来MVC后台逻辑

[HttpPost]
public ActionResult SyncUpload(HttpPostedFileBase file)
{
 using (var client = new HttpClient())
 {
  using (var content = new MultipartFormDataContent())
  {
   byte[] Bytes = new byte[file.InputStream.Length + 1];
   file.InputStream.Read(Bytes, 0, Bytes.Length);
   var fileContent = new ByteArrayContent(Bytes);
          //设置请求头中的附件为文件名称,以便在WebAPi中进行获取
   fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = file.FileName };
   content.Add(fileContent);
   var requestUri = "http://localhost:8084/api/upload/post";
   var result = client.PostAsync(requestUri, content).Result;
   if (result.StatusCode == System.Net.HttpStatusCode.Created)
   {
            //获取到上传文件地址,并渲染到视图中进行访问
    var m = result.Content.ReadAsStringAsync().Result;
    var list = JsonConvert.DeserializeObject>(m);
    ViewBag.Success = list.FirstOrDefault();
 
   }
   else
   {
    ViewBag.Failed = "上传失败啦,状态码:" + result.StatusCode + ",原因:" + result.ReasonPhrase + ",错误信息:" + result.Content.ToString();
   }
  }
 }
 return View();
}

注意:上述将获取到文件字节流数组需要传递给 MultipartFormDataContent ,要不然传递到WebAPi时会获取不到文件数据。

到这里为止在MVC中操作就已经完毕,此时我们来看看在WebAPi中需要完成哪些操作。

(1)首先肯定需要判断上传的数据是否是MimeType类型。

if (!Request.Content.IsMimeMultipartContent())
{
 throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}

(2)我们肯定是需要重新生成一个文件名称以免重复,利用Guid或者Date或者其他。

string name = item.Headers.ContentDisposition.FileName.Replace("\"", "");
string newFileName = Guid.NewGuid().ToString("N") + Path.GetExtension(name);

(3)我们需要利用此类 MultipartFileStreamProvider 设置上传路径并将文件写入到这个里面。

var provider = new MultipartFileStreamProvider(rootPath);
var task = Request.Content.ReadAsMultipartAsync(provider).....

(4) 返回上传文件地址。

  return Request.CreateResponse(HttpStatusCode.Created, JsonConvert.SerializeObject(savedFilePath));
分步骤解析了这么多,组装代码如下:

public Task Post()
{
 List savedFilePath = new List();
 if (!Request.Content.IsMimeMultipartContent())
 {
  throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
 }
 var substringBin = AppDomain.CurrentDomain.BaseDirectory.IndexOf("bin");
 var path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, substringBin);
 string rootPath = path + "upload";
 var provider = new MultipartFileStreamProvider(rootPath);
 var task = Request.Content.ReadAsMultipartAsync(provider).
  ContinueWith(t =>
  {
   if (t.IsCanceled || t.IsFaulted)
   {
    Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
   }
   foreach (MultipartFileData item in provider.FileData)
   {
    try
    {
     string name = item.Headers.ContentDisposition.FileName.Replace("\"", "");
     string newFileName = Guid.NewGuid().ToString("N") + Path.GetExtension(name);
     File.Move(item.LocalFileName, Path.Combine(rootPath, newFileName));
               //Request.RequestUri.PathAndQury为需要去掉域名的后面地址
               //如上述请求为http://localhost:80824/api/upload/post,这就为api/upload/post
               //Request.RequestUri.AbsoluteUri则为http://localhost:8084/api/upload/post
     Uri baseuri = new Uri(Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.PathAndQuery, string.Empty));
     string fileRelativePath = rootPath +"\\"+ newFileName;
     Uri fileFullPath = new Uri(baseuri, fileRelativePath);
     savedFilePath.Add(fileFullPath.ToString());
    }
    catch (Exception ex)
    {
     string message = ex.Message;
    }
   }
 
   return Request.CreateResponse(HttpStatusCode.Created, JsonConvert.SerializeObject(savedFilePath));
  });
 return task;
}

注意:上述item.LocalFileName为 E:\Documents\Visual Studio 2013\Projects\WebAPiReturnHtml\WebAPiReturnHtml\upload\BodyPart_fa01ff79-4a5b-40f6-887f-ab514ec6636f ,因为此时我们重新命名了文件名称,所以需要将该文件移动到我们重新命名的文件地址。

整个过程就是这么简单,下面我们来看看演示结果。

ASP.NET WebAPi(selfhost)实现文件同步或异步上传

此时居然出错了,有点耐人寻味,在服务端是返回如下的Json字符串

List savedFilePath = new List();

此时进行反序列化时居然出错,再来看看页面上的错误信息:

ASP.NET WebAPi(selfhost)实现文件同步或异步上传

无法将字符串转换为List,这不是一一对应的么,好吧,我来看看返回的字符串到底是怎样的,【当将鼠标放上去】时查看的如下:

ASP.NET WebAPi(selfhost)实现文件同步或异步上传

【当将点击查看】时结果如下:

ASP.NET WebAPi(selfhost)实现文件同步或异步上传

由上知点击查看按钮时返回的才是正确的json,到了这里我们发现Json.NET序列化时也是有问题的,于是乎在进行反序列化时将返回的字符串需要进行一下处理转换成正确的json字符串来再来进行反序列化,修改如下:     

var m = result.Content.ReadAsStringAsync().Result;
    m = m.TrimStart('\"');
    m = m.TrimEnd('\"');
    m = m.Replace("\\", "");
    var list = JsonConvert.DeserializeObject>(m);

到这里我们的同步上传告一段落了,这里面利用Json.NET进行反序列化时居然出错问题,第一次遇到Json.NET反序列化时的问题,比较奇葩,费解。

QIMI奇觅
QIMI奇觅

美图推出的游戏行业广告AI制作与投放一体化平台

下载

异步上传

所谓的异步上传不过是利用Ajax进行上传,这里也就是为了复习下脚本或者Razor视图,下面的内容只是将视图进行了修改而已,对于异步上传我利用了jquery.form.js中的异步api,请看如下代码:





 
@using (Ajax.BeginForm("AsyncUpload", "Home", new AjaxOptions() { HttpMethod = "POST" }, new { enctype = "multipart/form-data",@style="margin-top:10px;" })) {
}

我们截图看下其中上传过程

上传中:

ASP.NET WebAPi(selfhost)实现文件同步或异步上传

上传完成:

当然这里的100%不过是针对小文件的实时上传,如果是大文件肯定不是实时的,利用其它组件来实现更加合适,这里我只是学习学习仅此而已。

注意:这里还需重申一遍,之前在MVC上传已经叙述过,MVC默认的上传文件是有限制的,所以超过其限制,则无法上传,需要进行如下设置

(1)在IIS 5和IIS 6中,默认文件上传的最大为4兆,当上传的文件大小超过4兆时,则会得到错误信息,但是我们通过如下来设置文件大小。


 

   

(2)在IIS 7+,默认文件上传的最大为28.6兆,当超过其默认设置大小,同样会得到错误信息,但是我们却可以通过如下来设置文件上传大小(同时也要进行如上设置)。


 
  
   
  
 

   

总结 

本节我们学习了如何将MVC和WebAPi隔离开来来进行上传,同时我们也发现在反序列化时Json.NET有一定问题,特此记录下,当发现一一对应时反序列化返回的Json字符串不是标准的Json字符串,我们对返回的Json字符串需要作出如下处理才行(也许还有其他方案)。               

var jsonString = "返回的json字符串";
jsonString = jsonString.TrimStart('\"');
jsonString = jsonString.TrimEnd('\"');
jsonString = jsonString.Replace("\\", "");

   

接下来会准备系统学习下SQL Server和Oracle,循序渐进,你说呢!休息,休息!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

13

2026.01.29

clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址
clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址

clawdbot龙虾机器人官网入口:https://clawd.bot/,clawdbot ai是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

3

2026.01.29

Golang 网络安全与加密实战
Golang 网络安全与加密实战

本专题系统讲解 Golang 在网络安全与加密技术中的应用,包括对称加密与非对称加密(AES、RSA)、哈希与数字签名、JWT身份认证、SSL/TLS 安全通信、常见网络攻击防范(如SQL注入、XSS、CSRF)及其防护措施。通过实战案例,帮助学习者掌握 如何使用 Go 语言保障网络通信的安全性,保护用户数据与隐私。

5

2026.01.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

539

2026.01.28

包子漫画在线官方入口大全
包子漫画在线官方入口大全

本合集汇总了包子漫画2026最新官方在线观看入口,涵盖备用域名、正版无广告链接及多端适配地址,助你畅享12700+高清漫画资源。阅读专题下面的文章了解更多详细内容。

187

2026.01.28

ao3中文版官网地址大全
ao3中文版官网地址大全

AO3最新中文版官网入口合集,汇总2026年主站及国内优化镜像链接,支持简体中文界面、无广告阅读与多设备同步。阅读专题下面的文章了解更多详细内容。

320

2026.01.28

php怎么写接口教程
php怎么写接口教程

本合集涵盖PHP接口开发基础、RESTful API设计、数据交互与安全处理等实用教程,助你快速掌握PHP接口编写技巧。阅读专题下面的文章了解更多详细内容。

10

2026.01.28

php中文乱码如何解决
php中文乱码如何解决

本文整理了php中文乱码如何解决及解决方法,阅读节专题下面的文章了解更多详细内容。

16

2026.01.28

Java 消息队列与异步架构实战
Java 消息队列与异步架构实战

本专题系统讲解 Java 在消息队列与异步系统架构中的核心应用,涵盖消息队列基本原理、Kafka 与 RabbitMQ 的使用场景对比、生产者与消费者模型、消息可靠性与顺序性保障、重复消费与幂等处理,以及在高并发系统中的异步解耦设计。通过实战案例,帮助学习者掌握 使用 Java 构建高吞吐、高可靠异步消息系统的完整思路。

10

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP基础入门课程
PHP基础入门课程

共33课时 | 2万人学习

极致CMS零基础建站教学视频
极致CMS零基础建站教学视频

共62课时 | 5.5万人学习

Golang进阶实战编程
Golang进阶实战编程

共34课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号