webapi实现AJAX多文件上传,ASP.NET WebAPi(selfhost)之文件同步或异步上传

同步上传

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

copycode.gif

@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;" }))

{        

}

copycode.gif

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

copycode.gif[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("p_w_upload") { 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();

}

copycode.gif

注意:上述将获取到文件字节流数组需要传递给 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));

分步骤解析了这么多,组装代码如下:

copycode.gifpublic 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;

}

copycode.gif

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

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

589642-20161106232857205-591777729.png

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

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

589642-20161106233054221-936941078.png

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

589642-20161106233158346-200839884.png

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

589642-20161106233420299-1962821209.png

由上知点击查看按钮时返回的才是正确的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字符串首末尾的\和多出的\\去掉。然后再来看看反序列的数据

589642-20161106234044393-1015294193.png

最终在页面显示如下:

589642-20161106234249143-1566083367.png

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

异步上传

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

copycode.gif

上传成功文件访问地址

上传失败

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

{    

0%

.progress {

position: relative;

width: 400px;

border: 1px solid #ddd;

padding: 1px;

}

.progress-bar {

width: 0px;

height: 40px;

background-color: #57be65;

}

(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();

}

}

});

})();

copycode.gif

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

上传中:

589642-20161106235104815-1927860614.png

上传完成:

589642-20161106235125315-358780896.png

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

注意:这里还需重申一遍,之前在MVC上传已经叙述过,MVC默认的上传文件是有限制的,所以超过其限制,则无法上传,需要进行如下设置(1)在IIS 5和IIS 6中,默认文件上传的最大为4兆,当上传的文件大小超过4兆时,则会得到错误信息,但是我们通过如下来设置文件大小。

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

copycode.gif

copycode.gif

copycode.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值