如何为multipart / form-data设置web api控制器

时间:2015-02-06 15:49:21

标签: c# asp.net-web-api multipartform-data

我正在试图弄清楚如何完成这项工作。我没有使用我的代码获得任何有用的错误消息,所以我使用其他东西来生成一些东西。我在错误消息后附加了该代码。我找到了tutorial,但我不知道如何用我所拥有的实现它。这就是我目前所拥有的

public async Task<object> PostFile()
    {
        if (!Request.Content.IsMimeMultipartContent())
            throw new Exception();


        var provider = new MultipartMemoryStreamProvider();
        var result = new { file = new List<object>() };
        var item = new File();

        item.CompanyName = HttpContext.Current.Request.Form["companyName"];
        item.FileDate = HttpContext.Current.Request.Form["fileDate"];
        item.FileLocation = HttpContext.Current.Request.Form["fileLocation"];
        item.FilePlant = HttpContext.Current.Request.Form["filePlant"];
        item.FileTerm = HttpContext.Current.Request.Form["fileTerm"];
        item.FileType = HttpContext.Current.Request.Form["fileType"];

        var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
        var user = manager.FindById(User.Identity.GetUserId());

        item.FileUploadedBy = user.Name;
        item.FileUploadDate = DateTime.Now;

        await Request.Content.ReadAsMultipartAsync(provider)
         .ContinueWith(async (a) =>
         {
             foreach (var file in provider.Contents)
             {
                 if (file.Headers.ContentLength > 1000)
                 {
                     var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
                     var contentType = file.Headers.ContentType.ToString();
                     await file.ReadAsByteArrayAsync().ContinueWith(b => { item.FilePdf = b.Result; });
                 }


             }


         }).Unwrap();

        db.Files.Add(item);
        db.SaveChanges();
        return result;

    }

错误

  

对象{message:&#34;请求实体的媒体类型&#39; multipart / form-data&#39;此资源不支持。&#34;,exceptionMessage:&#34;没有MediaTypeFormatter可用于阅读具有媒体类型&multi39 / form-data&#39;。&#34;的内容。 exceptionType:&#34; System.Net.Http.UnsupportedMediaTypeException&#34;,stackTrace:&#34;在System.Net.Http.HttpContentExtensions.ReadAs ... atterLogger,CancellationToken cancellationToken)&#34;} exceptionMessage:&#34;没有MediaTypeFormatter可用于读取&#39; HttpPostedFileBase&#39;来自内容与媒体类型&#39; multipart / form-data&#39;。&#34; exceptionType:&#34; System.Net.Http.UnsupportedMediaTypeException&#34; message:&#34;请求实体&#39;媒体类型&#39; multipart / form-data&#39;此资源不支持。&#34; stackTrace:&#34; at System.Net.Http.HttpContentExtensions.ReadAsAsync [T](HttpContent content,Type type,IEnumerable 1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken) ↵ at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable 1 formatters,IFormatterLogger formatterLogger,CancellationToken cancellationToken)

用于生成错误消息的代码

    [HttpPost]
    public string UploadFile(HttpPostedFileBase file)
    {

        if (file.ContentLength > 0)
        {
            var fileName = Path.GetFileName(file.FileName);
            var path = Path.Combine(HttpContext.Current.Server.MapPath("~/uploads"), fileName);
            file.SaveAs(path);


        }
        return "/uploads/" + file.FileName;
    }

public class File
{
    public int FileId { get; set; }
    public string FileType { get; set; }
    public string FileDate { get; set; }
    public byte[] FilePdf { get; set; }
    public string FileLocation { get; set; }
    public string FilePlant { get; set; }
    public string FileTerm { get; set; }
    public DateTime? FileUploadDate { get; set; }
    public string FileUploadedBy { get; set; }

    public string CompanyName { get; set; }
    public virtual ApplicationUser User { get; set; }
}

8 个答案:

答案 0 :(得分:70)

我通常只在 Mvc控制器中使用 HttpPostedFileBase 参数。处理 ApiControllers 时,请尝试检查传入文件的 HttpContext.Current.Request.Files 属性:

[HttpPost]
public string UploadFile()
{
    var file = HttpContext.Current.Request.Files.Count > 0 ?
        HttpContext.Current.Request.Files[0] : null;

    if (file != null && file.ContentLength > 0)
    {
        var fileName = Path.GetFileName(file.FileName);

        var path = Path.Combine(
            HttpContext.Current.Server.MapPath("~/uploads"),
            fileName
        );

        file.SaveAs(path);
    }

    return file != null ? "/uploads/" + file.FileName : null;
}

答案 1 :(得分:42)

这就解决了我的问题 将以下行添加到WebApiConfig.cs

config.Formatters.XmlFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data"));

答案 2 :(得分:13)

你可以使用这样的东西

[HttpPost]
public async Task<HttpResponseMessage> AddFile()
{
    if (!Request.Content.IsMimeMultipartContent())
    {
        this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
    }

    string root = HttpContext.Current.Server.MapPath("~/temp/uploads");
    var provider = new MultipartFormDataStreamProvider(root);
    var result = await Request.Content.ReadAsMultipartAsync(provider);

    foreach (var key in provider.FormData.AllKeys)
    {
        foreach (var val in provider.FormData.GetValues(key))
        {
            if (key == "companyName")
            {
                var companyName = val;
            }
        }
    }

    // On upload, files are given a generic name like "BodyPart_26d6abe1-3ae1-416a-9429-b35f15e6e5d5"
    // so this is how you can get the original file name
    var originalFileName = GetDeserializedFileName(result.FileData.First());

    var uploadedFileInfo = new FileInfo(result.FileData.First().LocalFileName);
    string path = result.FileData.First().LocalFileName;

    //Do whatever you want to do with your file here

    return this.Request.CreateResponse(HttpStatusCode.OK, originalFileName );
}

private string GetDeserializedFileName(MultipartFileData fileData)
{
    var fileName = GetFileName(fileData);
    return JsonConvert.DeserializeObject(fileName).ToString();
}

public string GetFileName(MultipartFileData fileData)
{
    return fileData.Headers.ContentDisposition.FileName;
}

答案 3 :(得分:5)

5年后,.NET Core 3.1允许您这样指定媒体类型:

"devDependencies": {
    "axios": "^0.19",
    "bootstrap": "^4.0.0",
    "cross-env": "^7.0",
    "jquery": "3.4.1",
    "laravel-mix": "^5.0.1",
    "lodash": "^4.17.13",
    "popper.js": "^1.12",
    "resolve-url-loader": "^2.3.1",
    "sass": "^1.20.1",
    "sass-loader": "^8.0.0",
    "vue": "^2.5.17",
    "vue-template-compiler": "^2.6.10"
}

答案 4 :(得分:3)

检查你的WebApiConfig并添加这个

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

答案 5 :(得分:1)

也许派对晚了。 但是,还有一个替代解决方案是使用ApiMultipartFormFormatter插件。

此插件可以像ASP.NET Core一样帮助您接收multipart / formdata内容。

在github页面上,已经提供了演示。

答案 6 :(得分:0)

这是ASP.Net Core解决此问题的另一个答案...

在Angular方面,我举了这个代码示例...

https://stackblitz.com/edit/angular-drag-n-drop-directive

...并对其进行了修改以调用HTTP Post端点:

  prepareFilesList(files: Array<any>) {

    const formData = new FormData();
    for (var i = 0; i < files.length; i++) { 
      formData.append("file[]", files[i]);
    }

    let URL = "https://localhost:44353/api/Users";
    this.http.post(URL, formData).subscribe(
      data => { console.log(data); },
      error => { console.log(error); }
    );

完成此操作后,这是我在ASP.Net Core WebAPI控制器中所需的代码:

[HttpPost]
public ActionResult Post()
{
  try
  {
    var files = Request.Form.Files;

    foreach (IFormFile file in files)
    {
        if (file.Length == 0)
            continue;
        
        string tempFilename = Path.Combine(Path.GetTempPath(), file.FileName);
        System.Diagnostics.Trace.WriteLine($"Saved file to: {tempFilename}");

        using (var fileStream = new FileStream(tempFilename, FileMode.Create))
        {
            file.CopyTo(fileStream);
        }
    }
    return new OkObjectResult("Yes");
  }
  catch (Exception ex)
  {
    return new BadRequestObjectResult(ex.Message);
  }
}

非常简单,但是我不得不从几个(几乎正确的)资源中整理示例,以使其正常工作。

答案 7 :(得分:-3)

您正在获取HTTP 415“此资源不支持请求实体的媒体类型'multipart / form-data'。”因为您没有在请求中提及正确的内容类型。