ASP.NET Core多文件上传触发Synchronous operations are disallowed错误如何解决
问题根因
- 自定义的
AllowSynchronousIOAttribute触发时机错误:你重写的是OnResultExecuting方法,这个方法是在控制器Action执行完成、准备返回结果的时候才会运行,此时上传文件的逻辑已经执行完毕,修改AllowSynchronousIO完全不会生效。 - 直接报错来源:
PostAsBinaryAsync扩展方法中调用了同步方法inputStream.CopyTo(stream),这个操作会同步读取请求的Body流,触发ASP.NET Core默认的同步IO禁止规则。
解决方案1(推荐:无兼容问题,无需开启同步IO)
直接修改PostAsBinaryAsync方法,把同步的CopyTo替换为异步的CopyToAsync即可,完全符合异步编程规范,不需要修改任何全局或者请求级的IO配置:
public static async Task<HttpResponseMessage> PostAsBinaryAsync( this HttpClient client, string requestUri, Stream inputStream, string fileName, CancellationToken cancellationToken = default(CancellationToken)) { using (var stream = new MemoryStream()) { // 把同步CopyTo替换为异步CopyToAsync await inputStream.CopyToAsync(stream, cancellationToken); using (var content = new ByteArrayContent(stream.ToArray())) { content.Headers.ContentType = new MediaTypeHeaderValue("application/binary"); return await client.PostAsync( requestUri, content, cancellationToken) .ConfigureAwait(false); } } }
另外UploadFileAsync里的stream.Position = 0可以直接删除,MultipartReader返回的section.Body本身不支持seek操作,这行代码不会产生实际效果。
解决方案2(兼容场景:无法修改Zendesk客户端代码时使用)
如果不能修改引用的Zendesk客户端代码,就修正AllowSynchronousIOAttribute的触发时机,把配置修改操作提前到Action执行之前:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class AllowSynchronousIOAttribute : ActionFilterAttribute { // 重写OnActionExecuting在Action执行前修改配置 public override void OnActionExecuting(ActionExecutingContext context) { // 通用服务配置 var syncIOFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>(); if (syncIOFeature != null) { syncIOFeature.AllowSynchronousIO = true; } // IIS InProcess托管专属配置 var iisSyncFeature = context.HttpContext.Features.Get<Microsoft.AspNetCore.Server.IIS.Core.IIsHttpBodyControlFeature>(); if (iisSyncFeature != null) { iisSyncFeature.AllowSynchronousIO = true; } base.OnActionExecuting(context); } }
修改完成后将特性标记到Upload控制器方法上即可生效。
内容的提问来源于stack exchange,提问作者Oleg Sh
相关产品推荐
相关产品推荐

