簡體   English   中英

FileExtensions屬性-使用Enumerator作為參數

[英]FileExtensions attribute - using Enumerator as a parameter

長話短說-我有一個Entity Framework模型,該模型接受Enum類型的屬性:

public class FileUploads {
    public AllowedFileTypes FileType { get; set; }
}

枚舉是:

public enum AllowedFileTypes {
    jpg,
    png,
    gif,
    jpeg,
    bmp,
}

然后,在Web API控制器中,我為IFormFile設置一個驗證屬性,如下所示:

[HttpPost]
public async Task<IActionResult> Upload(
    [Required]
    [FileExtensions(Extensions = "jpg,png,gif,jpeg,bmp")] // allowed filetypes
    IFormFile file)
{
    return Ok()
}

該方法用於上傳文件。 現在,問題是我基本上是在手動設置FileExtensions屬性允許的格式。 這意味着以后無論何時將新文件格式添加到枚舉中,我都需要手動更新每個FileExtensions屬性。 這很容易被遺忘,或者任何其他開發人員都無法意識到這一事實。

所以,我在想是否可以將Enum類型參數傳遞給FileExtensions屬性?

我的嘗試如下:

[FileExtensions(Extensions = string.Join(",", Enum.GetValues(typeof(FileExtensions))))]

不幸的是, Extensions參數必須是const類型的字符串,因此VS會引發錯誤。 我當然可以編寫自己的自定義驗證屬性,例如:

FileExtensions fileExtension;
bool fileExtensionParseResult = Enum.TryParse<FileExtensions>(Path.GetExtension(file.FileName), true, out fileExtension);

還有其他想法嗎?

因此,當我處理白名單時,通常使用配置文件,而不是將其硬編碼到應用程序中。 另外,我將利用Content-Type標頭來確定請求的內容類型。 上傳jpg時,他們應該發送諸如image / jpeg之類的內容。

如果這樣做不能為您提供足夠的入門信息,請發表評論,我將舉一個快速的例子。

編輯:

這是我自己的項目中的一個示例。 在appsettings.json中,添加以下內容:

"AllowedFileUploadTypes": {
    "image/jpeg": "jpg",
    "video/quicktime": "mov"
  }

我通常創建一個包裝類來訪問設置,下面是我的.NET Core版本的示例:

using System.Linq;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;

public class AppConfigurationManager
{
    private IConfiguration _configuration;

    public AppConfigurationManager(IConfiguration configuration)
    {
        _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
    }

    public IDictionary<string, string> AllowedFileUploadTypes =>
                    _configuration.GetSection(nameof(AllowedFileUploadTypes)).GetChildren()
                        .Select(item => new KeyValuePair<string, string>(item.Key, item.Value))
                        .ToDictionary(x => x.Key, x => x.Value);

}

當然,您必須在Startup.cs中注冊

public class Startup
{
    public Startup(IConfiguration configuration)
    {            
        Configuration = configuration;

    }
    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        //stuff...
        services.AddSingleton(Configuration);
        services.AddSingleton<AppConfigurationManager>();
        //other stuff...
    }
}

然后,您可以使用AppConfigurationManager.AllowedFileUploadTypes評估IFormFile.ContentType屬性,以驗證文件的內容類型是否有效。 您可以嘗試從字典中獲取值,然后針對該屬性進行驗證。 根據文檔,我假設ContentType屬性將由Content-Type標頭填充。 我通常使用塊上傳文件,因此我沒有使用IFormFile

編輯:想要一種適用於該操作的方法。

使用ActionFilterAttribute,您可以執行以下操作:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

public class ValidateFileExtensionsAttribute : ActionFilterAttribute
{

    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var fileKeyValue = context.ActionArguments.FirstOrDefault(x => typeof(IFormFile).IsAssignableFrom(x.Value.GetType()));

        if (fileKeyValue.Value != null)
        {
            AppConfigurationManager sessionService = context.HttpContext.RequestServices.GetService(typeof(AppConfigurationManager)) as AppConfigurationManager;
            IFormFile fileArg = fileKeyValue.Value as IFormFile;

            if (!sessionService.AllowedFileUploadTypes.Keys.Any(x => x == fileArg.ContentType))
            {
                context.Result = new ObjectResult(new { Error = $"The content-type '{fileArg.ContentType}' is not valid." }) { StatusCode = 400 };

                //or you could set the modelstate
                //context.ModelState.AddModelError(fileKeyValue.Key, $"The content-type '{fileArg.ContentType}' is not valid.");
                return;
            }
        }

        await next();
    }
}

然后,您可以將其應用於以下操作:

[HttpPost]
[ValidateFileExtensions]
public async Task<IActionResult> Upload([Required]IFormFile file)
{
    return Ok();
}

您可以修改ActionFilter來設置ModelState,也可以只返回該值。

〜干杯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM