Receive file and other form data together in ASP.N

2020-02-26 05:42发布

How would you form your parameters for the action method which is supposed to receive one file and one text value from the request?

I tried this

public string Post([FromBody]string name, [FromBody]IFormFile imageFile)

And tried hitting it from Postman but it gives me 500 Internal Server Error. I also can't debug it because it never hits the first statement inside the action method where I've put my breakpoint.

Any idea how can we parse boundary based requests and extract file(s) and other textual field(s)? I am new to ASP.NET Core.

6条回答
时光不老,我们不散
2楼-- · 2020-02-26 06:08

In HomeController.cs

using Microsoft.AspNetCore.Hosting;
.......
private IHostingEnvironment _environment;

public HomeController(IHostingEnvironment environment)
{
    _environment = environment;
}

[HttpPost]
[ValidateAntiForgeryToken]        
public IActionResult Index(IFormCollection formdata)
{
 var files = HttpContext.Request.Form.Files;
 foreach (var file in files)
 {
     var uploads = Path.Combine(_environment.WebRootPath, "Images");
     if (file.Length > 0)
     {
        string FileName = Guid.NewGuid(); // Give file name
        using (var fileStream = new FileStream(Path.Combine(uploads, FileName), FileMode.Create))
        {
            file.CopyToAsync(fileStream);
        }       
     }
  }
}

In view - Index.cshtml

<form method="post" enctype="multipart/form-data" >
 .....
</form>

You can try this code.

Thanks!!

查看更多
smile是对你的礼貌
3楼-- · 2020-02-26 06:11

I'm using the following code to accomplish this in order to parse a response from Mailgun, which comprises both files and text values.

Please note that "dashifying" is just so property names like "MessageHeaders" get turned into "message-headers"; obviously you should use whatever logic makes sense for your use case.

Controller:

using System;
using Microsoft.AspNetCore.Mvc;
using NuGet.Protocol.Core.v3;

namespace Potato
{
    [Route("api/[controller]")]
    public class MailgunController : Controller
    {
        [HttpPost]
        public IActionResult Post()
        {
            MailgunEmail email = new MailgunEmail(Request);

            return Ok(email.ToJson());
        }
    }
}

Model:

using System;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;

namespace Potato
{
    public class MailgunEmail
    {
        public IEnumerable<IFormFile> Attachments { get; set; }

        public string Recipient { get; set; }
        public string Sender { get; set; }
        public string From { get; set; }
        public string Subject { get; set; }
        public string BodyPlain { get; set; }
        public string StrippedText { get; set; }
        public string StrippedSignature { get; set; }
        public string BodyHtml { get; set; }
        public string StrippedHtml { get; set; }
        public int? AttachmentCount { get; set; }
        public int Timestamp { get; set; }
        public string Token { get; set; }
        public string Signature { get; set; }
        public string MessageHeaders { get; set; }
        public string ContentIdMap { get; set; }

        public MailgunEmail(HttpRequest request)
        {
            var form = request.Form;

            Attachments = new List<IFormFile>(form.Files);

            foreach (var prop in typeof(MailgunEmail).GetProperties()) {
                string propName = Dashify(prop.Name);
                var curVal = form[propName];
                if (curVal.Count > 0) {
                    prop.SetValue(this, To(curVal[0], prop.PropertyType), null);
                }
            }
        }

        private object To(IConvertible obj, Type t)
        {
            Type u = Nullable.GetUnderlyingType(t);

            if (u != null) {
                return (obj == null) ? GetDefaultValue(t) : Convert.ChangeType(obj, u);
            } else {
                return Convert.ChangeType(obj, t);
            }
        }

        private object GetDefaultValue(Type t)
        {
            if (t.GetTypeInfo().IsValueType) {
                return Activator.CreateInstance(t);
            }
            return null;
        }

        private string Dashify(string source)
        {
            string result = "";
            var chars = source.ToCharArray();
            for (int i = 0; i < chars.Length; ++i) {
                var c = chars[i];
                if (i > 0 && char.IsUpper(c)) {
                    result += '-';
                }
                result += char.ToLower(c);
            }
            return result;
        }
    }
}
查看更多
We Are One
4楼-- · 2020-02-26 06:11

You Can Get Multi Images By Sample Code Through MultiPart.

First Inject IHttpContextAccessor To ConfigureService Method In Startup Class.Then Call It With Constructor Injection In Controller:

        private readonly IHttpContextAccessor _httpContextAccessor;

          public FileController(IHttpContextAccessor httpContextAccessor)
                {
                    _httpContextAccessor = httpContextAccessor;           
                }

Action Method Can Have Response Or Not.

        public async Task<object> UploadImage()
            {
                var fileBytes = new List<byte[]>();
                var files = 
                   _httpContextAccessor.HttpContext.Request.Form.Files;

            foreach (var file in files)
            {
                if (file.Length > 0)
                {
                    using (var memoryStream = new MemoryStream())
                    {
                        await file.CopyToAsync(memoryStream);
                        fileBytes.Add(memoryStream.ToArray());
                    }
                }
            }
   // TODO: Write Code For Save Or Send Result To Another Services For Save
            }
查看更多
该账号已被封号
5楼-- · 2020-02-26 06:31

I guess you're transmitting the file and text in proper JSON format.

You should create a new class which includes file and text as properties of type string. Add the new class to your method arguments with attribute[FromBody] and you'll be able to parse the image string according to your needs.

Another way would be accessing the whole request content via

await Request.Content.ReadAsStringAsync();

You would then have to parse the entire content, though.

查看更多
仙女界的扛把子
6楼-- · 2020-02-26 06:34

I had the similar issue and I solved the problem by using [FromForm] attribute and FileUploadModelView in the function as follow:

[HttpPost]
        [Route("upload")]
        public async Task<IActionResult> Upload([FromForm] FileUploadViewModel model, [FromForm] string member_code)
        {
            var file = model.File;

            ...
        }
查看更多
Ridiculous、
7楼-- · 2020-02-26 06:34

This page helped me a lot https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads

so now in my code I have the controller method as:

 public async Task<IActionResult> UploadFiles(UploadedFile ups)

and a class for the model as

public class UploadedFile
    {
        public string UploadName { get; set; }
        public List<IFormFile> Files { get; set; }
    }

and the form like

<form method="post" enctype="multipart/form-data" asp-controller="Files" asp-action="UploadFiles">
查看更多
登录 后发表回答