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

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

细谈 Web Api 图片上传,在使用 Task.ContinueWith 变量无法赋值问题的解决办法!
[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

你可能感兴趣的:(continue)