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

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

同步上传

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

<div> <div> @if (ViewBag.Success != null) { <div role="alert"> <strong>成功啦 !</strong> 成功上传. <a href="https://www.jb51.net/@ViewBag.Success" target="_blank">open file</a> </div> } else if (ViewBag.Failed != null) { <div 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> <input type="file" /> </div> <input type="submit" value="Submit" /> } </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为需要去掉域名的后面地址                  //如上述请求为:80824/api/upload/post,这就为api/upload/post                  //Request.RequestUri.AbsoluteUri则为: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; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjygys.html