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 MultipartMemoryStreamProvider
to 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");
}