如何使用 Web API 上传文件 AND 模型?

How to upload file AND model using Web API?

提问人:J. Doe 提问时间:3/17/2016 更新时间:3/1/2023 访问量:7350

问:

基本上,我正在尝试使用 Web API 2 上传图像和枚举。

下面是控制器签名:

[HttpPost]
public UploadResponseVm Upload([FromBody]ResImageType type)
{

问题是,每当我尝试发布多部分表单(带有文件和类型)时,我都会收到 415 错误:

{“Message”:“请求实体的媒体类型'multipart/form-data'为: 此资源不支持“,”ExceptionMessage“:”否 MediaTypeFormatter 可用于读取 “ResImageType”(来自具有媒体类型的内容) 'multipart/form-data'.“,”ExceptionType“:”System.Net.Http.UnsupportedMediaTypeException“,”StackTrace“:” 在 System.Net.Http.HttpContentExtensions.ReadAsAsync [T] (HttpContent 内容、类型类型、IEnumerable1 格式化程序、IFormatterLogger formatterLogger, CancellationToken cancellationToken)“}1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable

我什至将以下内容添加到我的启动.cs类中:

    config.Formatters.Insert(0, new System.Net.Http.Formatting.JsonMediaTypeFormatter());

如何使用 Web API 控制器上传模型和文件?

asp.net rest http asp.net-web-api2

评论


答:

0赞 Niko 1/9/2018 #1

没有格式化程序可以处理/关联您的对象。我曾经使用无参数方法在没有格式化程序的情况下解决了类似的问题,并处理了方法中的数据。例如:ResImageType

public async Task<HttpResponseMessage> PostFormData()
    {
        if (!Request.Content.IsMimeMultipartContent("form-data"))
        {
            return Request.CreateResponse(HttpStatusCode.BadRequest);
        }

            string upDir= "PathOfDirectory";

            MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider(upDir);                
            MultipartFileStreamProvider multipartFileStreamProvider = await Request.Content.ReadAsMultipartAsync(streamProvider);

            // Loop through files.
            foreach (MultipartFileData file in streamProvider.FileData)
            {
                // Save filepaths to DB or do something else
            }
            return Request.CreateResponse(HttpStatusCode.OK);
    }

MS Docs 的类似解决方案

另一种可能性是创建一个类似 DTO 的类,用于传输对象并使用格式化程序,例如 MultipartDataMediaFormatter 似乎是合法的(尚未尝试过)。

0赞 Hammad Shabbir 2/24/2020 #2

您可以通过在标头请求中添加内容类型来同时添加媒体和枚举。

Content-Type:application/x-www-form-urlencoded

然后尝试访问文件和枚举

[HttpPost]
public UploadResponseVm Upload()
{
            //Get enum type
            var enumkey = HttpContext.Current.Request.Form.AllKeys.FirstOrDefault(x => x == "enumkey");
            var enumType = Convert.ToInt32(HttpContext.Current.Request.Form[enumkey]).ToEnum<ResImageType>();

            //Access files
            var postedFileLst = HttpContext.Current.Request.Files.GetMultiple("fileKey").ToList();
}

使用 Extension Method 转换为枚举

public static T ToEnum<T>(this int param)
{
            var info = typeof(T);
            if (info.IsEnum)
            {
                T result = (T)Enum.Parse(typeof(T), param.ToString(), true);
                return result;
            }

            return default(T);
}

同时使用 curl 进行验证

curl --location --request POST '{{hostname}}/api/media/addmedia' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--form 'BookLogos=@/path/to/file' \
--form 'enumkey=1'
0赞 Hamza Iftikhar 3/1/2023 #3

如果您有以下代码更改,以下示例将解决该问题。

放置参数[FromForm]

public async Task<ActionResult<Guid>> Create([FromForm] CreateEmployeeCommand command)

和在模型中

public class CreateEmployeeCommand
{
    public IFormFile FormFile { get; set; }
    public string AnyData { get; set; }
}

使用 JS 对象向控制器发送数据FormDataPOST