细谈 Web Api 图片上传,在使用 Task.ContinueWith 变量无法赋值问题的解决办法!

 

在使用Asp.Net Web Api 图片上传接口的时候,到网上找了一些个例子,但大多数找到都是这个版本!

[HttpPost]
public Task<Hashtable> ImgUpload()
{
// 检查是否是 multipart/form-data
if (!Request.Content.IsMimeMultipartContent("form-data"))
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
//文件保存目录路径
string SaveTempPath = "~/SayPlaces/" + "/SayPic/SayPicTemp/";
String dirTempPath = HttpContext.Current.Server.MapPath(SaveTempPath);
// 设置上传目录
var provider = new MultipartFormDataStreamProvider(dirTempPath);
//var queryp = Request.GetQueryNameValuePairs();//获得查询字符串的键值集合
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<Hashtable>(o =>
{
Hashtable hash = new Hashtable();
hash["error"] = 1;
hash["errmsg"] = "上传出错";
var file = provider.FileData[0];//provider.FormData
string orfilename = file.Headers.ContentDisposition.FileName.TrimStart('"').TrimEnd('"');
FileInfo fileinfo = new FileInfo(file.LocalFileName);
//最大文件大小
int maxSize = 10000000;
if (fileinfo.Length <= 0)
{
hash["error"] = 1;
hash["errmsg"] = "请选择上传文件。";
}
else if (fileinfo.Length > maxSize)
{
hash["error"] = 1;
hash["errmsg"] = "上传文件大小超过限制。";
}
else
{
string fileExt = orfilename.Substring(orfilename.LastIndexOf('.'));
//定义允许上传的文件扩展名
String fileTypes = "gif,jpg,jpeg,png,bmp";
if (String.IsNullOrEmpty(fileExt) || Array.IndexOf(fileTypes.Split(','), fileExt.Substring(1).ToLower()) == -1)
{
hash["error"] = 1;
hash["errmsg"] = "上传文件扩展名是不允许的扩展名。";
}
else
{
String ymd = DateTime.Now.ToString("yyyyMMdd", System.Globalization.DateTimeFormatInfo.InvariantInfo);
String newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", System.Globalization.DateTimeFormatInfo.InvariantInfo);
fileinfo.CopyTo(Path.Combine(dirTempPath, newFileName + fileExt), true);
fileinfo.Delete();
hash["error"] = 0;
hash["errmsg"] = "上传成功";
}
}
return hash;
});
return task;
}

[HttpPost]
public Task<Hashtable> ImgUpload()
{
// 检查是否是 multipart/form-data
if (!Request.Content.IsMimeMultipartContent("form-data"))
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
//文件保存目录路径
string SaveTempPath = "~/SayPlaces/" + "/SayPic/SayPicTemp/";
String dirTempPath = HttpContext.Current.Server.MapPath(SaveTempPath);
// 设置上传目录
var provider = new MultipartFormDataStreamProvider(dirTempPath);
//var queryp = Request.GetQueryNameValuePairs();//获得查询字符串的键值集合
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<Hashtable>(o =>
{
Hashtable hash = new Hashtable();
hash["error"] = 1;
hash["errmsg"] = "上传出错";
var file = provider.FileData[0];//provider.FormData
string orfilename = file.Headers.ContentDisposition.FileName.TrimStart('"').TrimEnd('"');
FileInfo fileinfo = new FileInfo(file.LocalFileName);
//最大文件大小
int maxSize = 10000000;
if (fileinfo.Length <= 0)
{
hash["error"] = 1;
hash["errmsg"] = "请选择上传文件。";
}
else if (fileinfo.Length > maxSize)
{
hash["error"] = 1;
hash["errmsg"] = "上传文件大小超过限制。";
}
else
{
string fileExt = orfilename.Substring(orfilename.LastIndexOf('.'));
//定义允许上传的文件扩展名
String fileTypes = "gif,jpg,jpeg,png,bmp";
if (String.IsNullOrEmpty(fileExt) || Array.IndexOf(fileTypes.Split(','), fileExt.Substring(1).ToLower()) == -1)
{
hash["error"] = 1;
hash["errmsg"] = "上传文件扩展名是不允许的扩展名。";
}
else
{
String ymd = DateTime.Now.ToString("yyyyMMdd", System.Globalization.DateTimeFormatInfo.InvariantInfo);
String newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", System.Globalization.DateTimeFormatInfo.InvariantInfo);
fileinfo.CopyTo(Path.Combine(dirTempPath, newFileName + fileExt), true);
fileinfo.Delete();
hash["error"] = 0;
hash["errmsg"] = "上传成功";
}
}
return hash;
});
return task;
}

如果只是上传,简单用是可以的,但是你可能不会发现有什么问题。但如果你在Request.Content.ReadAsMultipartAsync(provider).ContinueWith 延时Task任务 里面赋值一个变量,你就会发现 始终赋值不上,不信你可以试试。

例子 如下:

public string UploadFile()
{
if (Request.Content.IsMimeMultipartContent())
{
//Save file
MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(HttpContext.Current.Server.MapPath("~/Files"));string filename = "Not set"; Request.Content.ReadAsMultipartAsync(provider).ContinueWith(o =>
{
//File name
filename = "Set success";
}, TaskScheduler.FromCurrentSynchronizationContext()); return filename;
}
else
{
return "Invalid.";
}
}

上面的得出的结果:  filename = "Not set" ;

注意如下结论

经测试发现如下结论,在执行 Request.Content.ReadAsMultipartAsync(provider).ContinueWith 异步延时任务的时候,先不会被立即执行。

等待 return 结束之后才会被执行。这也就是为什么返回的总是: "Not set" 

经过几天的摸索测试,在StackOverFlow上找到了一个解决的办法如下:

IEnumerable<HttpContent> parts = null;
Task.Factory
.StartNew(() => parts = Request.Content.ReadAsMultipartAsync().Result.Contents,
CancellationToken.None,
TaskCreationOptions.LongRunning, // guarantees separate thread
TaskScheduler.Default)
.Wait();

改造后就变成了这样,真的太棒了!

 public string UploadFile()
{
if (Request.Content.IsMimeMultipartContent())
{
//Save file
MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(HttpContext.Current.Server.MapPath("/UploadUser/")); string filename = "Not set"; IEnumerable<HttpContent> parts = null;
Task.Factory
.StartNew(() =>
{
parts = Request.Content.ReadAsMultipartAsync(provider).Result.Contents;
filename = "Set Success";
},
CancellationToken.None,
TaskCreationOptions.LongRunning, // guarantees separate thread
TaskScheduler.Default)
.Wait(); return filename;
}
else
{
return "Invalid.";
}
}

相关Task的文章:

http://stackoverflow.com/questions/10502353/task-continuewith-execution-orderTa

http://www.strathweb.com/2012/08/a-guide-to-asynchronous-file-uploads-in-asp-net-web-api-rtm/

StackOverFlow 最终解决方案:

http://stackoverflow.com/questions/15201255/request-content-readasmultipartasync-never-returns

在寂寞的日子里沉淀自己,在程序的日子里找到自己,我为梦想而坚持!
 

Web Api 图片上传,在使用 Task.ContinueWith 变量无法赋值问题的更多相关文章

  1. 细谈 Web Api 图片上传,在使用 Task.ContinueWith 变量无法赋值问题的解决办法!

    在使用Asp.Net Web Api 图片上传接口的时候,到网上找了一些个例子,但大多数找到都是这个版本! [HttpPost] public Task<Hashtable> ImgUpl ...

  2. Asp.Net Core Web Api图片上传(一)集成MongoDB存储实例教程

    Asp.Net Core Web Api图片上传及MongoDB存储实例教程(一) 图片或者文件上传相信大家在开发中应该都会用到吧,有的时候还要对图片生成缩略图.那么如何在Asp.Net Core W ...

  3. Asp.Net Web Api 图片上传

    public string UploadFile()        {            if (Request.Content.IsMimeMultipartContent())         ...

  4. web前端图片上传(3)--filereader

    这篇文章主要是为了介绍一种文件上传的方式.当然文件中是包含图片的.如果大家仔细看我的第一篇web前端图片上传(1)就会知道,其实也是按照这种方式上传你的,但是由于上次时间比较紧张,没有详细的介绍今天的 ...

  5. java web开发 图片上传功能

    基本思路在于,配置路径,然后用java I/O的api将图片上传到该目录下. String photoPath =    ServletActionContext.getServletContext( ...

  6. web前端图片上传

    图片上传有很多种形式,但是听说ios只能传字符串,所以为了安卓.ios和web能用一个接口上传图片,采用了基于base64 的方法上传图片. 下面是我的html <div class=" ...

  7. Asp.Net Core 3.0 学习3、Web Api 文件上传 Ajax请求以及跨域问题

    1.创建Api项目 我用的是VS2019 Core3.1 .打开Vs2019 创建Asp.Net Core Web应用程序命名CoreWebApi 创建选择API 在Controller文件夹下面添加 ...

  8. Uploadify 结合 Web API 2 上传问题

    最近使用jQuery.Uploadify和Web API配合来做上传,碰到问题,还木有办法解决,记录一下: 环境:jQuery 1.10.2,Uploadify 3.2.1,SWFObject 2.2 ...

  9. asp.net web api 文件上传

    1正确的做法 public class AvaterController : BaseApiController { [HttpPost] public async Task<IHttpActi ...

随机推荐

  1. zoj 3823 Excavator Contest(结构体)

    题目链接:zoj 3823 Excavator Contest 题目大意:一个人开着挖掘机要在N*N的格子上面移动.要求走全然部的格子.而且转完次数要至少为n*(n-1) - 1次, 而且终点和起点必 ...

  2. 使用ExpandableListView时间轴效果达到

    不废话,首先在地图上,查看结果 这是用ExpandableListView来实现时间轴效果,原理比較简单,以月份为第一级,以天为第二级来实现的. package com.hj.main; import ...

  3. unity3d 学习笔记_____Native2d 刚体、冲击、联合使用

    Mass Mass of the rigidbody. Linear Drag Drag coefficient affecting positional movement. Angular Drag ...

  4. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(13)-权限设计

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(13)-权限设计 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据 ...

  5. myEclipse Debug

    ========================================== myEclipse Debug     快捷键 ================================= ...

  6. Debug和Release的不同

     1. 变量. 大家都知道,debug跟release在初始化变量时所做的操作是不同的,debug是将每个字节位都赋成0xcc(注1),而release的赋值近似于随机(我想是直接从内存中分配的,没有 ...

  7. 判断sqlserver对象是否存在

    --查看对象是否已经存在  --数据库是否存在     --if exists (select * from sys.databases where name = ’数据库名’)    --  dro ...

  8. C#中的Params、ref、out的区别

    C# Params params params 关键字可以指定在参数数目可变处采用参数的方法参数. 在方法声明中的 params 关键字之后不允许任何其他参数,并且在方法声明中只允许一个 params ...

  9. oracle_面试题

    SELECT a.name ,IFNULL(b.name,"BOSS") FROM boss a LEFT JOIN boss b ON a.MANAGER_ID = b.ID 员 ...

  10. Swift得知——使用和分类功能(四)

    Swift得知--使用和分类功能(四) 总结Swift该功能使用的总可分为七类 1 ---- 没有返回值,没有參数的函数 2 ---- 有參数和返回值的函数 3 ---- 使用元祖来返回多个值 4 - ...