C# Asp.Net核心API CORS策略错误仅在文件上载中

C# Asp.Net核心API CORS策略错误仅在文件上载中,c#,api,asp.net-core,cors,C#,Api,Asp.net Core,Cors,我只有在使用AspNet Core API 3.1将文件上载到服务器时出现CORS策略阻止错误。以不同的方式向startup添加cors策略和使用自定义中间件并没有解决我的问题 启动: //配置服务 services.AddCors(options => { options.AddPolicy("EnableSVCCors", builder => { builder .Allow

我只有在使用AspNet Core API 3.1将文件上载到服务器时出现CORS策略阻止错误。以不同的方式向startup添加cors策略和使用自定义中间件并没有解决我的问题

启动:

//配置服务

    services.AddCors(options =>
    {
        options.AddPolicy("EnableSVCCors", builder =>
        {
            builder
                .AllowAnyOrigin()
                .AllowAnyHeader()
                .AllowAnyMethod()
                .Build();
        });
    });
//配置

    app.UseCors("EnableSVCCors");
通过从react客户端网站调用,所有API方法均可正常工作,但在尝试上载图像时,我出现以下错误:

访问位于的XMLHttpRequest "来源" “”已被CORS策略阻止:否 “Access Control Allow Origin”标头出现在请求的服务器上 资源

我还尝试更改cors策略,如下所示,但不起作用:

    services.AddCors(options =>
    {
        options.AddPolicy("EnableSVCCors", builder =>
        {
            builder
                .WithOrigins("http://172.16.1.35:3000")
                .AllowAnyHeader()
                .AllowAnyMethod()
                .Build();
        });
    });
注意:使用PostMan调用并将base64字符串作为图像发送工作正常!所以,对要保存图像的文件夹的访问限制没有问题

我还尝试添加自定义中间件,如下所示,但尚未工作:

    public class CorsMiddleWare
    {
        private readonly RequestDelegate _next;

        public CorsMiddleWare(RequestDelegate next)
        {
            _next = next;
        }

    public Task Invoke(HttpContext httpContext)
    {
        httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "http://172.16.1.35:3000");

        return _next(httpContext);
    }
}

public static class CorsMiddlewareExtensions
{
    public static IApplicationBuilder UseCorsMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<CorsMiddleWare>();
    }
}
公共类Corsmidware
{
private readonly RequestDelegate\u next;
公共CorsMiddle软件(RequestDelegate下一步)
{
_下一个=下一个;
}
公共任务调用(HttpContext HttpContext)
{
httpContext.Response.Headers.Add(“访问控制允许源站”http://172.16.1.35:3000");
返回_next(httpContext);
}
}
公共静态类CorsMiddlewareExtensions
{
公共静态IApplicationBuilder UseCorsMiddle软件(此IApplicationBuilder)
{
返回builder.UseMiddleware();
}
}
有人知道吗

编辑:控制台中的返回标题如下所示

请求URL: 推荐人政策:降级时无推荐人日期:2020年4月14日星期二 03:50:49 GMT服务器:Microsoft IIS/10.0传输编码:分块 X-Powered-By:ASP.NET Accept:application/json,text/plain/ 接受编码:gzip,deflate接受语言:en-US,en;q=0.9 授权:持票人 eyJhb。。。。。 连接:保持活动内容长度:22869内容类型: 应用程序/json;字符集=UTF-8主机:172.16.1.34:1980原点: 推荐人: 用户代理:Mozilla/5.0 (Windows NT 10.0;Win64;x64)AppleWebKit/537.36(KHTML,如Gecko) Chrome/80.0.3987.163 Safari/537.36{文件名:“阿凡达”,媒体类型: “image/png”,…}文件名:“avatar”媒体类型:“image/png”缓冲区: “IVBORW0KGGOAAAANSUHEUGAAAPOAAD6CAYAAACI7FO9AAGAE


通过更改对象类型解决的问题是将映像文件发送到MultipartDataMediaFormatter.V2中包含的HttpFile

上传视图模型:

public class ProfileAvatarUploadViewModel
{
    public HttpFile Image { get; set; }
}
Api控制器:

[HttpPost("UploadAvatar")]
[Authorize(AuthenticationSchemes = "Bearer", Roles = "Manager,Admin,User")]
public async Task<IActionResult> UploadAvatar([FromBody] ProfileAvatarUploadViewModel model)
{
    var userId = User.FindFirst(ClaimTypes.Name)?.Value;

    if (userId == null || !await _userAccountRepository.IsExists(int.Parse(userId)))
    {
        return Forbid();
    }

    var avatarToUpload = new ProfileAvatarUploadModel
    {
        UserAccountId = int.Parse(userId),
        UploadedImage = model.Image
    };

    var uploadedAvatar = await _profileAvatarRepository.UploadAvatar(avatarToUpload);

    return Ok(uploadedAvatar);
}
public async Task<ProfileAvatarViewModel> UploadAvatar(ProfileAvatarUploadModel model)
{
    var (key, value) = SVCardTools.SaveImage(model.UploadedImage);

    if (key.Equals(false))
    {
        throw new Exception(value);
    }

    var newAvatar = new ProfileAvatar
    {
        UserAccountId = model.UserAccountId,
        AvatarUrl = value,
        IsActive = false,
        IsPublic = false
    };

    _context.Entry(newAvatar).State = EntityState.Added;

    await _context.SaveChangesAsync();

    return ProfileAvatarViewModel.Set(newAvatar);
}
    public static KeyValuePair<bool, string> SaveImage(HttpFile file)
    {
        var bytes = file.Buffer;

        try
        {
            var fileExt = file.MediaType.Split('/')[1];
            switch (fileExt.ToLower())
            {
                case "png":
                    fileExt = ".png";
                    break;
                case "jpg":
                    fileExt = ".jpg";
                    break;
                default:
                    return new KeyValuePair<bool, string>(false, "Message");
            }

            var sb = new StringBuilder();
            sb.Append(DateTime.Now.Ticks);

            var saveFilePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot\\avatars",
                $"{sb}{fileExt}");

            var saveDbPath = $"{sb}{fileExt}";

            if (bytes.Length > 0)
            {
                using (var stream = new FileStream(saveFilePath, FileMode.Create))
                {
                    stream.Write(bytes, 0, bytes.Length);
                }
            }

            return new KeyValuePair<bool, string>(true, saveDbPath);

        }
        catch (Exception e)
        {
            var message = e.Message;
            return new KeyValuePair<bool, string>(false, message);
        }
    }
[HttpPost(“上传虚拟形象”)]
[授权(AuthenticationSchemes=“Bearer”,Roles=“经理、管理员、用户”)]
公共异步任务上载化身([FromBody]ProfileAvatarUploadViewModel模型)
{
var userId=User.FindFirst(ClaimTypes.Name)?.Value;
if(userId==null | |!wait _userAccountRepository.IsExists(int.Parse(userId)))
{
返回禁止();
}
var avatartouload=新档案avataruploadmodel
{
UserAccountId=int.Parse(userId),
UploadeImage=model.Image
};
var uploadedAvatar=wait _profileAvatarRepository.uploadeavatar(avatartopload);
返回Ok(uploadedAvatar);
}
存储库:

[HttpPost("UploadAvatar")]
[Authorize(AuthenticationSchemes = "Bearer", Roles = "Manager,Admin,User")]
public async Task<IActionResult> UploadAvatar([FromBody] ProfileAvatarUploadViewModel model)
{
    var userId = User.FindFirst(ClaimTypes.Name)?.Value;

    if (userId == null || !await _userAccountRepository.IsExists(int.Parse(userId)))
    {
        return Forbid();
    }

    var avatarToUpload = new ProfileAvatarUploadModel
    {
        UserAccountId = int.Parse(userId),
        UploadedImage = model.Image
    };

    var uploadedAvatar = await _profileAvatarRepository.UploadAvatar(avatarToUpload);

    return Ok(uploadedAvatar);
}
public async Task<ProfileAvatarViewModel> UploadAvatar(ProfileAvatarUploadModel model)
{
    var (key, value) = SVCardTools.SaveImage(model.UploadedImage);

    if (key.Equals(false))
    {
        throw new Exception(value);
    }

    var newAvatar = new ProfileAvatar
    {
        UserAccountId = model.UserAccountId,
        AvatarUrl = value,
        IsActive = false,
        IsPublic = false
    };

    _context.Entry(newAvatar).State = EntityState.Added;

    await _context.SaveChangesAsync();

    return ProfileAvatarViewModel.Set(newAvatar);
}
    public static KeyValuePair<bool, string> SaveImage(HttpFile file)
    {
        var bytes = file.Buffer;

        try
        {
            var fileExt = file.MediaType.Split('/')[1];
            switch (fileExt.ToLower())
            {
                case "png":
                    fileExt = ".png";
                    break;
                case "jpg":
                    fileExt = ".jpg";
                    break;
                default:
                    return new KeyValuePair<bool, string>(false, "Message");
            }

            var sb = new StringBuilder();
            sb.Append(DateTime.Now.Ticks);

            var saveFilePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot\\avatars",
                $"{sb}{fileExt}");

            var saveDbPath = $"{sb}{fileExt}";

            if (bytes.Length > 0)
            {
                using (var stream = new FileStream(saveFilePath, FileMode.Create))
                {
                    stream.Write(bytes, 0, bytes.Length);
                }
            }

            return new KeyValuePair<bool, string>(true, saveDbPath);

        }
        catch (Exception e)
        {
            var message = e.Message;
            return new KeyValuePair<bool, string>(false, message);
        }
    }
public异步任务上传化身(ProfileAvatarUploadModel模型)
{
var(key,value)=SVCardTools.SaveImage(model.UploadedImage);
if(key.Equals(false))
{
抛出新异常(值);
}
var newAvatar=newprofiler avatar
{
UserAccountId=model.UserAccountId,
AvatarUrl=值,
IsActive=false,
IsPublic=false
};
_context.Entry(newAvatar).State=EntityState.Added;
wait_context.SaveChangesAsync();
返回ProfileAvatarViewModel.Set(newAvatar);
}
保存图像功能:

[HttpPost("UploadAvatar")]
[Authorize(AuthenticationSchemes = "Bearer", Roles = "Manager,Admin,User")]
public async Task<IActionResult> UploadAvatar([FromBody] ProfileAvatarUploadViewModel model)
{
    var userId = User.FindFirst(ClaimTypes.Name)?.Value;

    if (userId == null || !await _userAccountRepository.IsExists(int.Parse(userId)))
    {
        return Forbid();
    }

    var avatarToUpload = new ProfileAvatarUploadModel
    {
        UserAccountId = int.Parse(userId),
        UploadedImage = model.Image
    };

    var uploadedAvatar = await _profileAvatarRepository.UploadAvatar(avatarToUpload);

    return Ok(uploadedAvatar);
}
public async Task<ProfileAvatarViewModel> UploadAvatar(ProfileAvatarUploadModel model)
{
    var (key, value) = SVCardTools.SaveImage(model.UploadedImage);

    if (key.Equals(false))
    {
        throw new Exception(value);
    }

    var newAvatar = new ProfileAvatar
    {
        UserAccountId = model.UserAccountId,
        AvatarUrl = value,
        IsActive = false,
        IsPublic = false
    };

    _context.Entry(newAvatar).State = EntityState.Added;

    await _context.SaveChangesAsync();

    return ProfileAvatarViewModel.Set(newAvatar);
}
    public static KeyValuePair<bool, string> SaveImage(HttpFile file)
    {
        var bytes = file.Buffer;

        try
        {
            var fileExt = file.MediaType.Split('/')[1];
            switch (fileExt.ToLower())
            {
                case "png":
                    fileExt = ".png";
                    break;
                case "jpg":
                    fileExt = ".jpg";
                    break;
                default:
                    return new KeyValuePair<bool, string>(false, "Message");
            }

            var sb = new StringBuilder();
            sb.Append(DateTime.Now.Ticks);

            var saveFilePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot\\avatars",
                $"{sb}{fileExt}");

            var saveDbPath = $"{sb}{fileExt}";

            if (bytes.Length > 0)
            {
                using (var stream = new FileStream(saveFilePath, FileMode.Create))
                {
                    stream.Write(bytes, 0, bytes.Length);
                }
            }

            return new KeyValuePair<bool, string>(true, saveDbPath);

        }
        catch (Exception e)
        {
            var message = e.Message;
            return new KeyValuePair<bool, string>(false, message);
        }
    }
publicstatickeyvaluepairsaveimage(HttpFile文件)
{
var bytes=file.Buffer;
尝试
{
var fileExt=file.MediaType.Split('/')[1];
开关(fileExt.ToLower())
{
案例“png”:
fileExt=“.png”;
打破
案例“jpg”:
fileExt=“.jpg”;
打破
违约:
返回新的KeyValuePair(false,“消息”);
}
var sb=新的StringBuilder();
sb.Append(DateTime.Now.Ticks);
var saveFilePath=Path.Combine(Directory.GetCurrentDirectory(),“wwwroot\\avatars”,
$“{sb}{fileExt}”);
var saveDbPath=$“{sb}{fileExt}”;
如果(bytes.Length>0)
{
使用(var stream=newfilestream(saveFilePath,FileMode.Create))
{
stream.Write(字节,0,字节.长度);
}
}
返回新的KeyValuePair(true,saveDbPath);
}
捕获(例外e)
{
var消息=e.消息;
返回新的KeyValuePair(错误,消息);
}
}

响应的HTTP状态码是什么?您可以使用浏览器devtools中的网络窗格进行检查。这是4xx还是5xx错误,而不是200 OK成功响应?@sideshowbarker它返回了(失败的网络::err_失败)。我用返回标题更新了我的问题。