簡體   English   中英

如何為多部分/表單數據設置 Web API controller

[英]How to set up a Web API controller for multipart/form-data

我試圖弄清楚這一點。 我的代碼沒有收到任何有用的錯誤消息,所以我使用了其他東西來生成一些東西。 我在錯誤消息后附上了該代碼。 我找到了一個關於它的教程,但我不知道如何用我所擁有的來實現它。 這是我目前擁有的:

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;

    }

錯誤:

Object {消息:“此資源不支持請求實體的媒體類型'multipart/form-data'。”,exceptionMessage:“沒有MediaTypeFormatter可用於讀取媒體類型為'multipart/form-data'的對象...om內容.", exceptionType: "System.Net.Http.UnsupportedMediaTypeException", stackTrace: " at System.Net.Http.HttpContentExtensions.ReadAs…atterLogger, CancellationToken cancellationToken)"}exceptionMessage: "No MediaTypeFormatter is available to read an object of type '來自媒體類型為“multipart/form-data”的內容的 HttpPostedFileBase'。”exceptionType:“System.Net.Http.UnsupportedMediaTypeException”消息:“此資源不支持請求實體的媒體類型“multipart/form-data”。” stackTrace:“在 System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent 內容,類型類型 , IEnumerable 1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken) ↵ at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable 1 格式化程序, IFormatterLogger formatterLogger, CancellationToken cancelToken)

用於生成錯誤消息的代碼:

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

Class:

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

我通常只在Mvc Controllers 中使用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;
}

這就是解決我的問題的原因
將以下行添加到 WebApiConfig.cs

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

你可以使用這樣的東西

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

也許聚會遲到了。 但是有一個替代解決方案是使用ApiMultipartFormFormatter插件。

此插件可幫助您像 ASP.NET Core 一樣接收 multipart/formdata 內容。

在github頁面中,已經提供了demo。

5 年后,.NET Core 3.1 允許您像這樣指定媒體類型:

[HttpPost]
[Consumes("multipart/form-data")]
public IActionResult UploadLogo()
{
    return Ok();
}

這是針對此問題的 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);
  }
}

令人震驚的簡單,但我必須將來自幾個(幾乎正確)來源的示例拼湊起來才能使其正常工作。

對我來說以這種方式工作,希望它有所幫助!

        [HttpPost("AddProduct")]

        public async Task<IActionResult> AddProduct( IFormFile files)
        {
            string fileGuid = Guid.NewGuid().ToString();
            var pathImage = Path.Combine(_hostEnvironment.ContentRootPath, "Images", fileGuid);
            var streamImage = new FileStream(pathImage, FileMode.Append);
            await files.CopyToAsync(streamImage);

            return Ok();

           
        }

對於 Asp.net MVC,我需要在保存文件之前進行驗證和處理,因此我通過更多步驟將文件賦予屬性來解決我的問題。 首先

HttpContext.Current.Request.Files[i]

是 HttpPostedFile 所以我用這種類型創建了一個屬性(我有多個文件並且需要更多屬性)所以我將文件分配給如下屬性

if (HttpContext.Current.Request.Files.Count>0)
        {

            var files = HttpContext.Current.Request.Files;
            for (int i = 0; i < files.Keys.Count; i++)
            {
                if (files.Keys[i].ToLower() == "ShenasnameImage".ToLower())
                {
                    model.ShenasnameImage = files[i];
                    
                }
                if (files.Keys[i].ToLower() == "MelliCardImage".ToLower())
                {
                    model.MelliCardImage = files[i];
                    
                }
            }
        }

然后我對文件屬性進行驗證和處理,最后保存文件。

檢查你的 WebApiConfig 並添加這個

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

您收到 HTTP 415“此資源不支持請求實體的媒體類型‘multipart/form-data’。” 因為您沒有在請求中提及正確的內容類型。

暫無
暫無

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

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