asp.net ReadAsMultipartAsync实际上是如何工作的?

bjp0bcyl  于 2022-11-19  发布在  .NET
关注(0)|答案(1)|浏览(241)

我使用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');
            }
        });
    }
}

我将整个data:image/jpeg;base64,业务替换为this post
在后端我有以下多部分控制器:

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);
    }
}

遗憾的是,streamProvider上的FileData被馈入ReadAsMultipartAsync方法,但它是空的:

我发现的另一件有趣的事情是上传的二进制文件被转义了,就像我在监 windows 口中注意到的那样:

%2f/字符的转义序列。
我实在找不到问题所在有人有什么建议吗

4si2a6ki

4si2a6ki1#

混合ContinueWith和async/await会导致问题,只要执行await Request.Content.ReadAsMultipartAsync(streamProvider);.ContinueWith中的所有内容都会像正常代码一样在await之后执行。
或者删除async/await并添加:

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

你也可以看看这个链接:Sending HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME

相关问题