Search code examples
asp.net-mvcrestpostfile-uploadasp.net-web-api

File Name from HttpRequestMessage Content


I implemented a POST Rest service to upload files to my server. The problem I have right now is that I want to restrict the uploaded files by its type. Let's say for example I only want to allow pdf files to be uploaded.

What I tried to do was:

Task<Stream> task = this.Request.Content.ReadAsStreamAsync();
task.Wait();
FileStream requestStream = (FileStream)task.Result;

but unfortunately its not possible to cast the Stream to a FileStream and access the type via requestStream.Name.

Is there an easy way (except writing the stream to the disk and check then the type) to get the filetype?


Solution

  • If you upload file to Web API and you want to get access to file data (Content-Disposition) you should upload the file as MIME multipart (multipart/form-data).

    Here I showed some examples on how to upload from HTML form, Javascript and from .NET.

    You can then do something like this, this example checks for pdf/doc files only:

    public async Task<HttpResponseMessage> Post()
        {
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable,
                                                                       "This request is not properly formatted - not multipart."));
            }
    
            var provider = new RestrictiveMultipartMemoryStreamProvider();
    
            //READ CONTENTS OF REQUEST TO MEMORY WITHOUT FLUSHING TO DISK
            await Request.Content.ReadAsMultipartAsync(provider);
    
            foreach (HttpContent ctnt in provider.Contents)
            {
                //now read individual part into STREAM
                var stream = await ctnt.ReadAsStreamAsync();
    
                if (stream.Length != 0)
                {
                    using (var ms = new MemoryStream())
                    {
                        //do something with the file memorystream
                    }
                }
            }
            return Request.CreateResponse(HttpStatusCode.OK);
        }
    }
    
    public class RestrictiveMultipartMemoryStreamProvider : MultipartMemoryStreamProvider
    {
        public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
        {
            var extensions = new[] {"pdf", "doc"};
            var filename = headers.ContentDisposition.FileName.Replace("\"", string.Empty);
    
            if (filename.IndexOf('.') < 0)
                return Stream.Null;
    
            var extension = filename.Split('.').Last();
    
            return extensions.Any(i => i.Equals(extension, StringComparison.InvariantCultureIgnoreCase))
                       ? base.GetStream(parent, headers)
                       : Stream.Null;
    
        }
    }