Web Api 图片上传,在使用 Task.ContinueWith 变量无法赋值问题
细谈 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 变量无法赋值问题的更多相关文章
- 细谈 Web Api 图片上传,在使用 Task.ContinueWith 变量无法赋值问题的解决办法!
在使用Asp.Net Web Api 图片上传接口的时候,到网上找了一些个例子,但大多数找到都是这个版本! [HttpPost] public Task<Hashtable> ImgUpl ...
- Asp.Net Core Web Api图片上传(一)集成MongoDB存储实例教程
Asp.Net Core Web Api图片上传及MongoDB存储实例教程(一) 图片或者文件上传相信大家在开发中应该都会用到吧,有的时候还要对图片生成缩略图.那么如何在Asp.Net Core W ...
- Asp.Net Web Api 图片上传
public string UploadFile() { if (Request.Content.IsMimeMultipartContent()) ...
- web前端图片上传(3)--filereader
这篇文章主要是为了介绍一种文件上传的方式.当然文件中是包含图片的.如果大家仔细看我的第一篇web前端图片上传(1)就会知道,其实也是按照这种方式上传你的,但是由于上次时间比较紧张,没有详细的介绍今天的 ...
- java web开发 图片上传功能
基本思路在于,配置路径,然后用java I/O的api将图片上传到该目录下. String photoPath = ServletActionContext.getServletContext( ...
- web前端图片上传
图片上传有很多种形式,但是听说ios只能传字符串,所以为了安卓.ios和web能用一个接口上传图片,采用了基于base64 的方法上传图片. 下面是我的html <div class=" ...
- Asp.Net Core 3.0 学习3、Web Api 文件上传 Ajax请求以及跨域问题
1.创建Api项目 我用的是VS2019 Core3.1 .打开Vs2019 创建Asp.Net Core Web应用程序命名CoreWebApi 创建选择API 在Controller文件夹下面添加 ...
- Uploadify 结合 Web API 2 上传问题
最近使用jQuery.Uploadify和Web API配合来做上传,碰到问题,还木有办法解决,记录一下: 环境:jQuery 1.10.2,Uploadify 3.2.1,SWFObject 2.2 ...
- asp.net web api 文件上传
1正确的做法 public class AvaterController : BaseApiController { [HttpPost] public async Task<IHttpActi ...
随机推荐
- Robot Framework自动化测试(一)---第一个脚本(转)
最近工具中用Robot Framework框架来做自动化,所以,花时间学习了一下. =======所需环境=================== Python: https://www.python. ...
- C# Parse和Convert的区别分析
原文:C# Parse和Convert的区别分析 大家都知道在进行类型转换的时候有连个方法供我们使用就是Convert.to和*.Parse,但是疑问就是什么时候用C 什么时候用P 通俗的解释大家都知 ...
- json 解析解乱码
1. 该法的字符编码: 串店txt文档文档都有自己的编码,例如utf-8,ansi等待,但当 存款txt文件.其编码将和txt编码文件本身一致. 例如,之前的字符编码ansi.txt该文件的编码是u ...
- 完整具体解释GCD系列(二)dispatch_after;dispatch_apply;dispatch_once
原创Blog,转载请注明出处 本文阅读的过程中,如有概念不懂,请參照前专栏中之前的文章,假设还有疑惑,请留言. 这是我关于GCD专栏的地址 http://blog.csdn.net/column/de ...
- 让Sqlite脱离VC++ Runtime独立执行
前段时间在开发OrayTalk(傲瑞通企业即时通信系统)的聊天记录模块时用到了Sqlite,这是我第一次接触和使用Sqlite,整体感觉还是很不错的.这里把我使用Sqlite的经验跟大家分享一下. 一 ...
- ListView排序并隔色显示
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.C ...
- MonkeyRunner于Windows在下面Eclipse开发环境的搭建步骤(并解决在线Jython配置错误的问题)
网上有一shangdong_chu网友写了一篇文章介绍了如何Eclipse构造MonkeyRunner,他做了叙述一个很好的说明.但我对我的环境试验后会见Jython解析错误的问题,和制品缺少Pyde ...
- Cocos2d-x学习笔记(14)(更新函数scheduleUpdate、进度计时器CCProgressTo、滚动视图CCScrollView)
一.scheduleUpdate 1.scheduleUpdate:此函数是CCNode的函数,每一个CCNode仅仅要调用scheduleUpdate更新函数,那么这个CCNode就会响应当前类的u ...
- PhpStorm 超强语言模板的支持
原文:[转]PhpStorm 超强语言模板的支持 最近遇到一些PhpStorm编程的问题: 在使用Zen Coding插件时,PHPStorm不像Notepad++那样随便使用.PHPStorm只有在 ...
- android KK版本号,如何更改蓝牙设备类型
mediatek/external/bluetooth/bt_cust/bt_cust_table.h { .name = "ClassOfDevice", ...