Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using MultipartFormDataStreamProvider and ReadAsMultipartAsync

How would i go about using MultipartFormDataStreamProvider and Request.Content.ReadAsMultipartAsync in a ApiController?

I have googled a few tutorials but I can't get any of them to work, I'm using .net 4.5.

Code:

public class TestController : ApiController
{
    const string StoragePath = @"T:\WebApiTest";
    public async void Post()
    {
        if (Request.Content.IsMimeMultipartContent())
        {
            var streamProvider = new MultipartFormDataStreamProvider(Path.Combine(StoragePath, "Upload"));
            await Request.Content.ReadAsMultipartAsync(streamProvider);
            foreach (MultipartFileData fileData in streamProvider.FileData)
            {
                if (string.IsNullOrEmpty(fileData.Headers.ContentDisposition.FileName))
                    throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
                    
                string fileName = fileData.Headers.ContentDisposition.FileName;
                
                if (fileName.StartsWith("\"") && fileName.EndsWith("\""))
                    fileName = fileName.Trim('"');
                    
                if (fileName.Contains(@"/") || fileName.Contains(@"\"))
                    fileName = Path.GetFileName(fileName);
                    
                File.Copy(fileData.LocalFileName, Path.Combine(StoragePath, fileName));
            }
        }
        else
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
        }
     }
}

I get the exception

Unexpected end of MIME multipart stream. MIME multipart message is not complete.

when the await task; runs. Does anyone know what I am doing wrong or have a working example in asp.net?

like image 405
Peter Avatar asked Dec 05 '12 21:12

Peter


People also ask

What is the use of Multipartformdatastreamprovider?

An IMultipartStreamProvider suited for use with HTML file uploads for writing file content to a FileStream. The stream provider looks at the <b>Content-Disposition</b> header field and determines an output Stream based on the presence of a <b>filename</b> parameter.

What is ReadAsMultipartAsync?

Description. ReadAsMultipartAsync(HttpContent) Reads all body parts within a MIME multipart message and produces a set of HttpContent instances as a result. ReadAsMultipartAsync(HttpContent, CancellationToken) Reads all body parts within a MIME multipart message and produces a set of HttpContent instances as a result.


2 Answers

I resolved the error, i don't understand what this has to do with end of multipart stream but here is the working code:

public class TestController : ApiController
{
    const string StoragePath = @"T:\WebApiTest";
    public async Task<HttpResponseMessage> Post()
    {
        if (Request.Content.IsMimeMultipartContent())
        {
            var streamProvider = new MultipartFormDataStreamProvider(Path.Combine(StoragePath, "Upload"));
            await Request.Content.ReadAsMultipartAsync(streamProvider);
            foreach (MultipartFileData fileData in streamProvider.FileData)
            {
                if (string.IsNullOrEmpty(fileData.Headers.ContentDisposition.FileName))
                {
                    return Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted");
                }
                string fileName = fileData.Headers.ContentDisposition.FileName;
                if (fileName.StartsWith("\"") && fileName.EndsWith("\""))
                {
                    fileName = fileName.Trim('"');
                }
                if (fileName.Contains(@"/") || fileName.Contains(@"\"))
                {
                    fileName = Path.GetFileName(fileName);
                }
                File.Move(fileData.LocalFileName, Path.Combine(StoragePath, fileName));
            }
            return Request.CreateResponse(HttpStatusCode.OK);
        }
        else
        {
            return Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted");
        }
    }
}
like image 101
Peter Avatar answered Oct 10 '22 11:10

Peter


At first, you should define enctype to multipart/form-data in ajax request header.

[Route("{bulkRequestId:int:min(1)}/Permissions")]
[ResponseType(typeof(IEnumerable<Pair>))]
public async Task<IHttpActionResult> PutCertificatesAsync(int bulkRequestId)
{
    if (Request.Content.IsMimeMultipartContent("form-data"))
    {
        string uploadPath = HttpContext.Current.Server.MapPath("~/uploads");

        var streamProvider = new MyStreamProvider(uploadPath);

        await Request.Content.ReadAsMultipartAsync(streamProvider);

        List<Pair> messages = new List<Pair>();
        
        foreach (var file in streamProvider.FileData)
        {
            FileInfo fi = new FileInfo(file.LocalFileName);
            messages.Add(new Pair(fi.FullName, Guid.NewGuid()));
        }

        //if (_biz.SetCertificates(bulkRequestId, fileNames))
        //{
            return Ok(messages);
        //}
        //return NotFound();
    }
    return BadRequest();
}

public class MyStreamProvider : MultipartFormDataStreamProvider
{
    public MyStreamProvider(string uploadPath) : base(uploadPath)
    {
    }
    public override string GetLocalFileName(HttpContentHeaders headers)
    {
        string fileName = Guid.NewGuid().ToString() + Path.GetExtension(headers.ContentDisposition.FileName.Replace("\"", string.Empty));
        return fileName;
    }
}
like image 22
Hamid Avatar answered Oct 10 '22 10:10

Hamid