博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET WebAPi(selfhost)之文件同步或异步上传
阅读量:6483 次
发布时间:2019-06-23

本文共 7237 字,大约阅读时间需要 24 分钟。

同步上传

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

复制代码

    
        @if (ViewBag.Success != null)        {            
                
成功啦 ! 成功上传. 
open file            
        }        else if (ViewBag.Failed != null)        {            
                
失败啦 ! @ViewBag.Failed                    }        @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 ,因为此时我们重新命名了文件名称,所以需要将该文件移动到我们重新命名的文件地址。

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

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

  List
 savedFilePath = new List
();

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

无法将字符串转换为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
>(m);

将上述返回的json字符串首末尾的\和多出的\\去掉。然后再来看看反序列的数据

最终在页面显示如下:

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

异步上传

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

复制代码

    
        
            
上传成功
文件访问地址                
        
            
上传失败            @using (Ajax.BeginForm("AsyncUpload", "Home", new AjaxOptions() { HttpMethod = "POST" }, new { enctype = "multipart/form-data",@style="margin-top:10px;" })){    
        
        
        
    }
    
        
0%        

复制代码

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

上传中: 

上传完成:

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

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

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

  

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

复制代码

复制代码

  
    
      
    
  

复制代码

本文转自帅气的头头博客51CTO博客,原文链接http://blog.51cto.com/12902932/1926508如需转载请自行联系原作者
sshpp
你可能感兴趣的文章
sscanf函数详解 & 查找文件字符串
查看>>
Java多线程系列目录(共43篇)
查看>>
Spring装配Bean---使用xml配置
查看>>
[洛谷P4311]士兵占领
查看>>
[HNOI2010]弹飞绵羊
查看>>
struct字节对齐原则
查看>>
从容的周6
查看>>
Sprite和UI Image的区别
查看>>
curl教程2
查看>>
slideout
查看>>
查询一个数据库中所有表的记录数
查看>>
maven学习之二
查看>>
jdk1.8api帮助文档,转载
查看>>
电商仓储管理的五个方向
查看>>
typeScript 装饰器
查看>>
jquery转换json对象为字符串 JSON.stringify(jsonObject)
查看>>
分享一个包括超多函数的Delphi函数单元
查看>>
文本分类五之朴素贝叶斯模块
查看>>
R语言可视化--ggplot函数
查看>>
大数据-01-安装Hadoop
查看>>