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

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

同步上传

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

<div class="container">
 <div>
  @if (ViewBag.Success != null)
  {
   <div class="alert alert-danger" role="alert">
    <strong>成功啦 !</strong> 成功上传. <a href="@ViewBag.Success" target="_blank">open file</a>
   </div>
  }
  else if (ViewBag.Failed != null)
  {
   <div class="alert alert-danger" role="alert">
    <strong>失败啦 !</strong> @ViewBag.Failed
   </div>
  }
 </div>
 @using (Html.BeginForm("SyncUpload", "Home", FormMethod.Post, new { role = "form", enctype = "multipart/form-data", @style = "margin-top:50px;" }))
 {
  <div class="form-group">
   <input type="file" id="file" name="file" />
  </div>
  <input type="submit" value="Submit" class="btn btn-primary" />
 }
</div>

上述我们直接上传后通过上传的状态来显示查看上传文件路径并访问,就是这么简单。下面我们来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<List<string>>(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<HttpResponseMessage> Post()
  {
   List<string> savedFilePath = new List<string>();
   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<HttpResponseMessage>(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 ,因为此时我们重新命名了文件名称,所以需要将该文件移动到我们重新命名的文件地址。

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

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

复制代码 代码如下:

List<string> savedFilePath = new List<string>();

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

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

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

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

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

最终在页面显示如下:

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

异步上传

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

<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.form.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />

<div class="container" style="margin-top:30px">
 <div id="success" style="display:none;">
  <div class="alert alert-danger" role="alert">
   <strong>上传成功</strong><span style="margin-right:50px;"></span><a href="" target="_blank" id="linkAddr">文件访问地址</a>
  </div>
 </div>

 <div id="fail" style="display:none;">
  <div class="alert alert-danger" role="alert">
   <strong>上传失败</strong>
  </div>
 </div>

</div>
@using (Ajax.BeginForm("AsyncUpload", "Home", new AjaxOptions() { HttpMethod = "POST" }, new { enctype = "multipart/form-data",@style="margin-top:10px;" }))
{
 <div class="form-group">
  <input type="file" name="file" id="fu1" />
 </div>
 <div class="form-group">
  <input type="submit" class="btn btn-primary" value="上传" />
 </div>

}

<div class="form-group">
 <div class="progress" id="progress" style="display:none;">
  <div class="progress-bar">0%</div>
 </div>
 <div id="status"></div>
</div>

<style>
 .progress {
  position: relative;
  width: 400px;
  border: 1px solid #ddd;
  padding: 1px;
 }

 .progress-bar {
  width: 0px;
  height: 40px;
  background-color: #57be65;
 }
</style>

<script>
 (function () {
  var bar = $('.progress-bar');
  var percent = $('.progress-bar');
  $('form').ajaxForm({
   beforeSend: function () {
    $("#progress").show();
    var percentValue = '0%';
    bar.width(percentValue);
    percent.html(percentValue);
   },
   uploadProgress: function (event, position, total, percentComplete) {
    var percentValue = percentComplete + '%';
    bar.width(percentValue);
    percent.html(percentValue);
   },
   success: function (d) {
    var percentValue = '100%';
    bar.width(percentValue);
    percent.html(percentValue);
    $('#fu1').val('');
   },
   complete: function (xhr) {
    if (xhr.responseText != null) {
     $("#linkAddr").prop("href", xhr.responseText);
     $("#success").show();
    }
    else {
     $("#fail").show();
    }
   }
  });
 })();
</script>

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

上传中:

上传完成:

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

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

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

<system.web>
 <httpRuntime maxRequestLength="2147483647" executionTimeout="100000" />
</system.web>

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

<system.webServer>
 <security>
  <requestFiltering>
   <requestLimits maxAllowedContentLength="2147483647" />
  </requestFiltering>
 </security>
</system.webServer>

总结

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

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

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

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索asp.net
, WebAPi异步上传
ASP.NET文件上传
,以便于您获取更多的相关知识。

时间: 2024-09-21 16:49:22

ASP.NET WebAPi(selfhost)实现文件同步或异步上传_实用技巧的相关文章

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

前言 前面我们讲过利用AngularJs上传到WebAPi中进行处理,同时我们在MVC系列中讲过文件上传,本文结合MVC+WebAPi来进行文件的同步或者异步上传,顺便回顾下css和js,MVC作为客户端,而WebAPi利用不依赖于IIS的selfhost模式作为服务端来接收客户端的文件且其过程用Ajax来实现,下面我们一起来看看. 同步上传 多余的话不用讲,我们直接看页面. <div class="container"> <div> @if (ViewBag.

asp.net下实现支持文件分块多点异步上传的 Web Services_实用技巧

本文的客户端应用程序不包括 ASP.Net Web 应用程序! 本文假设 URL: http://localhost/mywebservices/updownload.asmx 共有 4 个程序文件 (Web.Config 就不赘述了) Server Side:  标题中所提到的 "异步" 其实在服务器端的程序并没有什么特殊的,而主要是通过客户端应用程序 异步调用相关 Web Method 实现的! 1. updownload.asmx ,位于 IIS 的某个 Web 共享目录,代码如

asp.net fileupload控件上传文件与多文件上传_实用技巧

1.前台文件 Default.aspx: <%@ Page Language="C#" AutoEventWireup="true"CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.

ASP.NET实现读取Excel内容并在Web上显示_实用技巧

本文实例讲述了ASP.NET实现读取Excel内容并在Web上显示的方法,是非常实用的一个功能,分享给大家供大家参考.具体实现方法如下: 点击事件代码.cs代码如下: protected void Button1_Click(object sender, EventArgs e) { string strPath = "d:/test.xls"; string mystring = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source

ASP.NET中Web.config文件的层次关系详细介绍_实用技巧

Web.config 是一个基于 XML 的配置文件,该文件的作用是对应用程序进行配置,比如规定客户的认证方法,基于角色的安全技术的策略,数据绑 定的方法,远程处理对象等. 可以在网站的根目录和子目录下分别建立自己的 Web.config 文件,也可以一个Web.config 文件都不建立,Web.config 并不是网站必备的文件.这是因为服务器有一个总 的配置文件,名为"Machine.config" ,默认安装在"C:\Windows\Microsoft.NET\ Fr

asp.net slickupload 使用方法(文件上传)_实用技巧

在web.config中添加: <httpModules > <add name="HttpUploadModule" type="Krystalware.SlickUpload.HttpUploadModule, Krystalware.SlickUpload" / > </httpModules > 2.在项目中添加对Krystalware.SlickUpload.DLL的引用. 3.在页面上放控件:HtmlInputFile

asp.net 未能写入输出文件--“拒绝访问的解决办法_实用技巧

这个是网站部署在IIS7上出现的一个问题,解决办法是:   将C盘Windows目录下的Temp文件夹赋于IIS_IUSRS完全控制的权限即可,不用添加NETWORK SERVICE用户

ASP.NET之Excel下载模板、导入、导出操作_实用技巧

本文介绍了ASP.NET下Excel下载模板.导入.导出操作,供大家参考,具体内容如下 1.下载模板功能 protected void btnDownload_Click(object sender, EventArgs e) { var path = Server.MapPath(("upfiles\\") + "test.xlt"); //upfiles-文件夹 test.xlt-文件 var name = "test.xlt"; try {

asp.net上传图片并作处理水印与缩略图的实例代码_实用技巧

方法类: 复制代码 代码如下: upFileClass.cs using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlC