ReadAsMultipartAsync如何实际工作?

时间:2016-08-18 02:27:27

标签: c# asp.net .net asp.net-web-api multipartform-data

我在使用FormData API上传的网站中有一个canvas元素。我是这样做的:

upload: function (e) {
    var file = this.imagePreview.ui.canvas.get(0).toDataURL("image/jpeg")
                   .replace('data:image/jpeg;base64,', '');
    if (file) {
        var formData = new FormData();
        formData.append('file', file);
        $.ajax({
            url: app.getApiRoot + 'UserFiles/',
            type: "post",
            data: formData,
            processData: false,
            contentType: false,
            error: function () {
                $("#file_upload_result").html('there was an error while submitting');
            }
        });
    }
}

我按照this post替换整个data:image/jpeg;base64,商家。

在后端我有以下多部分控制器:

public async Task<IHttpActionResult> PostUserFile()
{
    string imageDir = ConfigurationManager.AppSettings["UploadedImageDir"];
    var PATH = HttpContext.Current.Server.MapPath("~/" + imageDir);
    var rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);

    if (Request.Content.IsMimeMultipartContent())
    {
        var streamProvider = new CustomMultipartFormDataStreamProvider(PATH);
        await Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith(t =>
        {
            if (t.IsFaulted || t.IsCanceled)
            {
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            }

            var files = streamProvider.FileData.Select(i =>
                        {
                            var info = new FileInfo(i.LocalFileName);
                            return new UserFile(User.Identity.GetUserId(), info.Name, rootUrl + "/" + imageDir + "/" + info.Name, info.Length / 1024);
                        });

            db.UserFiles.AddRange(files);
            db.SaveChangesAsync();
        });

        return Ok();
    }
    else
    {
        throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
    }
}

我实施CustomMultipartFormDataStreamProvider的地方如下:

public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
    public CustomMultipartFormDataStreamProvider(string path)
        : base(path)
    { }

    public override string GetLocalFileName(Headers.HttpContentHeaders headers)
    {
        var name = !string.IsNullOrWhiteSpace(headers.ContentDisposition.FileName) ? 
                      headers.ContentDisposition.FileName : 
                      "NoName";
        // This is here because Chrome submits files in quotation 
        // marks which get treated as part of the filename and get escaped
        return name.Replace("\"\"", string.Empty);
    }
}

可悲的是,FileData方法streamProvider上的ReadAsMultipartAsync为空:

FileData count = 0

我感到有趣的另一件事是上传的二进制文件被转义,正如我在观察窗口中注意到的那样:

Escaped data

%2f/字符的转义序列。

我根本无法 查明问题。有人有什么建议吗?

1 个答案:

答案 0 :(得分:0)

混合使用ContinueWith和async / await会导致出现问题,只需执行await Request.Content.ReadAsMultipartAsync(streamProvider);.ContinueWith中的所有内容都会像正常代码一样等待。

或删除async / await并添加:

return Request.Content.ReadAsMultipartAsync(streamProvider).Continu‌​eWith...

您也可以查看以下链接:Sending HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME