您的位置:首页 > 产品设计 > UI/UE

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

2015-04-17 14:50 786 查看
在使用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;
}


View Code

如果只是上传,简单用是可以的,但是你可能不会发现有什么问题。但如果你在 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐