Asp.Net Core API CORS 策略错误仅在文件上传中 [英] Asp.Net Core API CORS policy error only in file upload

查看:57
本文介绍了Asp.Net Core API CORS 策略错误仅在文件上传中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仅在使用 AspNet Core API 3.1 将文件上传到服务器时出现 CORS 策略阻止错误.以不同方式为启动添加 cors 策略并使用自定义中间件并没有解决我的问题.

I have CORS Policy blocking error only while uploading file to server using AspNet Core API 3.1. Adding cors policy to startup in different ways and using custom middleware not solved my problem.

启动:

//配置服务

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

//配置

    app.UseCors("EnableSVCCors");

通过从 React 客户端网站调用,所有 API 方法都可以正常工作,但在尝试上传图像时出现以下错误:

All API methods working fine by calling from react client web site but while trying to upload image I have following error:

访问 XMLHttpRequest 在'http://172.16.1.34:1980/api/accounts/uploadAvatar' 来自起源'http://172.16.1.35:3000' 已被 CORS 政策屏蔽:否请求中存在Access-Control-Allow-Origin"标头资源.

Access to XMLHttpRequest at 'http://172.16.1.34:1980/api/accounts/uploadAvatar' from origin 'http://172.16.1.35:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我也尝试按如下方式更改 cors 策略但不起作用:

I also try to change cors policy as below but not working:

    services.AddCors(options =>
    {
        options.AddPolicy("EnableSVCCors", builder =>
        {
            builder
                .WithOrigins("http://172.16.1.35:3000")
                .AllowAnyHeader()
                .AllowAnyMethod()
                .Build();
        });
    });

注意:调用http://172.16.1.34:1980/api/accounts/uploadAvatar 使用 PostMan 并发送 base64 字符串作为图像工作正常!因此,对将要保存图像的文件夹的访问限制没有问题.

Note: Calling http://172.16.1.34:1980/api/accounts/uploadAvatar using PostMan and sending base64 string as image is working fine! So there is no problem with access limits on folder where image going to be saved.

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

I also tried to add custom middleware as below but not working as yet:

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

有人知道吗?

控制台中的返回标题如下

EDIT : Return headers in console is as below

请求网址:http://172.16.1.34:1980/api/accounts/uploadAvatar推荐人政策:降级时无推荐人日期:2020 年 4 月 14 日,星期二03:50:49 GMT 服务器:Microsoft-IIS/10.0 传输编码:分块X-Powered-By:ASP.NET 接受:application/json、text/plain、/Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9授权:承载yjhb.....连接:保持活动内容长度:22869 内容类型:application/json;charset=UTF-8 主机:172.16.1.34:1980 来源:http://172.16.1.35:3000 推荐人:http://172.16.1.35:3000/create-profile 用户代理:Mozilla/5.0(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/80.0.3987.163 Safari/537.36 {文件名:头像",媒体类型:"image/png",...} fileName: "avatar" mediaType: "image/png" 缓冲区:"iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6CAYAAACI7Fo9AAAgAE

Request URL: http://172.16.1.34:1980/api/accounts/uploadAvatar Referrer Policy: no-referrer-when-downgrade Date: Tue, 14 Apr 2020 03:50:49 GMT Server: Microsoft-IIS/10.0 Transfer-Encoding: chunked X-Powered-By: ASP.NET Accept: application/json, text/plain, / Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Authorization: Bearer eyJhb..... Connection: keep-alive Content-Length: 22869 Content-Type: application/json;charset=UTF-8 Host: 172.16.1.34:1980 Origin: http://172.16.1.35:3000 Referer: http://172.16.1.35:3000/create-profile User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36 {fileName: "avatar", mediaType: "image/png",…} fileName: "avatar" mediaType: "image/png" buffer: "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6CAYAAACI7Fo9AAAgAE

推荐答案

通过改变对象类型解决的问题是作为图像文件发送到 HttpFile contains in MultipartDataMediaFormatter.V2 https://github.com/iLexDev/ASP.NET-WebApi-MultipartDataMediaFormatter

The problem solved by changing the type of object is sending as image file to HttpFile contains in MultipartDataMediaFormatter.V2 https://github.com/iLexDev/ASP.NET-WebApi-MultipartDataMediaFormatter

上传视图模型:

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

这篇关于Asp.Net Core API CORS 策略错误仅在文件上传中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆