問題:Request.Content.ReadAsMultipartAsync never returns

應用於使用FormData封包上傳(多段MIME)檔案時會卡住的狀況。有人查出原因是執行緒被自已鎖住。

修正前程式碼

/// 使用FormData封包上傳檔案之失敗例子
[HttpPost]
public string UploadFileSample_BAD()
{
    try
    {
        bool isMimeContent = Request.Content.IsMimeMultipartContent();
        var provider = Request.Content.ReadAsMultipartAsync().Result; 
        /// 使用 Task.Wait/Task.Result 同步語法將會自己鎖死自己的thread! Orz
        /// 然而改用 async/await 非同步語去就正常了。
        
        ...
        
        return $"SUCCESS";
    }
    catch (Exception ex)
    {
        return "我失敗了嗚嗚!";
    }
}

修正後程式碼

改用非同步語法(async/await)即可避開此問題。

/// <summary>
/// 使用FormData封包上傳檔案
/// </summary>
[HttpPost]
public async Task<string> UploadFileSample()
{
    try
    {
        //# 開始解析[MultipartFormDataContent]封包
        bool isMimeContent = Request.Content.IsMimeMultipartContent();
        var provider = await Request.Content.ReadAsMultipartAsync(); 
        /// 使用 Task.Wait/Task.Result 同步語法將會自己鎖死自己的thread!
        /// 然而改用 async/await 非同步語去就正常了。

        /// 再依FormData封包規格自行一一解開內容。
        /// 本案例第一個Content放資料,第二個之後放附件        
        
        //# 解開資料封包
        var reqContent = provider.Contents[0].ReadAsStringAsync().Result;
        var req = JsonConvert.DeserializeObject<YourFormInfo>(reqContent);

        //# 解開附件封包
        var streamList = new List<YourStreamInfo>();
        for (int i = 1; i < provider.Contents.Count; i++)
        {
            var content = provider.Contents[i];
            streamList.Add(new YourStreamInfo {
                name = content.Headers.ContentDisposition.Name,
                fileName = content.Headers.ContentDisposition.FileName,
                fileStream = content.ReadAsStreamAsync().Result
            });
        }

        // ...後續處理

        return $"SUCCESS;
    }
    catch (Exception ex)
    {
        return "我失敗了嗚嗚!";
    }
}

參考

Last updated