2

Problem

I started c# just last week, so it's entirely possible that I'm missing something obvious. Please help. I'm open to better ways.

I'm making a WebAPI file upload endpoint that postpones saving until it confirm the file's signatures.


I receive this error in Postman:

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


Per this stackoverflow answer, I receive the error because I start a second memory stream while the first is still open.

My code is below.


Efforts to Resolve problem:

I tried to implement this, this, and many others over the past two days.

A similar question is posed, unanswered, here.


Code So Far

C# code snippets not runnable in Stack Overflow.

I'm using MultipartMemoryStreamProviderto create a stream and get the file signatures. I created a CustomMultipartMemoryStream to inherit the IDisposable interface:

View CustomMultipartMemoryStreamProvider Class

public class CustomMultipartMemoryStreamProvider : MultipartMemoryStreamProvider, IDisposable
{
    public void Dispose()
    {
    }
}


I then create a using statement to get start the CustomMultipartMemoryStream, get the signatures, and confirm if the file is a JPEG. I then dispose of the stream:

View MultipartMemoryStreamProvider Implementation

bool isJpeg;

using (var MemoryStream = await Request.Content.ReadAsMultipartAsync(new CustomMultipartMemoryStreamProvider()))
{
    try
    {
        //Get Signatures works.
        //It uses Stream.Read to read the first 6 bytes of the stream
        //returns byte[]

        byte[] FileSignature = GetSignature(await MemoryStream.Contents[0].ReadAsStreamAsync());

        //HasJpegHeaders works.
        //It returns true or false
        isJpeg = HasJpegHeader(FileSignature);
    }
    finally
    {
        //This should dispose of the stream.
        //It runs.
        MemoryStream.Dispose();
    }

}

View GetSignature (WORKS)

static byte[] GetSignature(Stream stream)
{
    int offset = 0;
    byte[] fileSignature = new byte[6];
    while (offset < 6)
    {

        int read = stream.Read(fileSignature, offset, 6 - offset);
        if (read == 0)
            throw new System.IO.EndOfStreamException();
        offset += read;
    }
    stream.Position = 0;


    return fileSignature;

}

View HasJpegHeader (WORKS)

static bool HasJpegHeader(byte[] FileSignature)
{
    byte[] SoiArray = FileSignature.Take(2).ToArray();

    byte[] MarkerArray = FileSignature.Skip(2).Take(2).ToArray();

    bool result =  ((SoiArray.SequenceEqual(new byte[]{ 255, 216 })) &&     (MarkerArray.SequenceEqual(new byte[] { 255, 224 })));
    return result;
}


If the file is a jpeg, I start a CustomMultipartFormDataStreamProvider, which is the same as the MultipartFormDataStreamProvider except that it keeps the filenames on save.

The await Request.Content.ReadAsMultipartAsync(provider) throws the error (noted with an arrow.)

View CustomMultipartFormDataStreamProvider

if (isJpeg)
{
    string fileSaveLocation = HttpContext.Current.Server.MapPath("~/App_Data");

    CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(fileSaveLocation);
    List<string> files = new List<string>();

    try
    {

here be error-->await Request.Content.ReadAsMultipartAsync(provider);

        foreach (MultipartFileData file in provider.FileData)
        {
            files.Add(Path.GetFileName(file.LocalFileName));
        }

        // Send OK Response along with saved file names to the client.
        return Request.CreateResponse(HttpStatusCode.OK, files);
    }
    catch (System.Exception e)
    {
        return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
    }

}
else
{
    return Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted");   
}
cgousley
  • 21
  • 3

0 Answers0