web-dev-qa-db-fra.com

Comment configurer un contrôleur API Web pour multipart / form-data

J'essaie de comprendre cela. Je ne recevais aucun message d'erreur utile avec mon code, j'ai donc utilisé autre chose pour générer quelque chose. J'ai joint ce code après le message d'erreur. J'ai trouvé un tutoriel mais je ne sais pas comment le mettre en œuvre avec ce que j'ai. C'est ce que j'ai actuellement:

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;

    }

Erreur:

Object {message: "Le type de média de l'entité de demande 'multipart/form-data' n'est pas pris en charge pour cette ressource.", ExceptionMessage: "Aucun MediaTypeFormatter n'est disponible pour lire un contenu d'objet avec le type de média" multipart/form-data ". . ", exceptionType:" System.Net.Http.UnsupportedMediaTypeException ", stackTrace:" at System.Net.Http.HttpContentExtensions.ReadAs… atterLogger, CancellationToken cancelToken) "} exceptionMessage:" Aucun MediaTypeFormatter n'est disponible pour lire un objet de type " HttpPostedFileBase 'du contenu avec le type de média' multipart/form-data '. "ExceptionType:" System.Net.Http.UnsupportedMediaTypeException "message:" Le type de média de l'entité de la demande' multipart/form-data 'n'est pas pris en charge pour cette ressource. " stackTrace: "at System.Net.Http.HttpContentExtensions.ReadAsAsync [T] (contenu HttpContent, type, IEnumerable1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken) ↵ at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable 1 formateurs, IFormatterLogger formatterLogger, CancellationToken annulationToken)

Code utilisé pour générer le message d'erreur:

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

Classe:

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

J'utilise normalement le paramètre HttpPostedFileBase uniquement dans contrôleurs Mvc. Lorsque vous traitez avec ApiControllers, essayez plutôt de vérifier la propriété HttpContext.Current.Request.Files pour les fichiers entrants:

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

C'est ce qui a résolu mon problème
Ajoutez la ligne suivante à WebApiConfig.cs

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

Vous pouvez utiliser quelque chose comme ça

[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;
}
13
Dakshal Raijada

vérifiez votre WebApiConfig et ajoutez ceci

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
3
Liu Jaguar

Peut-être qu'il est tard pour la fête. Mais il existe une solution alternative pour utiliser le plugin ApiMultipartFormFormatter .

Ce plugin vous aide à recevoir le contenu multipart/formdata comme le fait ASP.NET Core.

Dans la page github, la démo est déjà fournie.

2
Redplane