C# HttpListener: storing posted file is always 2 byte larger than original
<p><strong>Problem description:</strong></p>

<p>I have an <code>HttpListener</code> within my C# program that takes a POST request with a posted file (jpg, doc, zip or alike). I am sending and receiving the file on the same Windows machine.</p>

<p>I took the code from
<a href="https://stackoverflow.com/a/8468520/241475">https://stackoverflow.com/a/8468520/241475</a> (coming from the Java world, I'm fairly new to C#/.Net), which is said to just be a proof of concept, and the upload and storing of data on the server side almost works fine, except that <strong>the stored files is always 2 bytes larger than the original</strong>.</p>

<p>This does not matter for jpg, doc or single zip files - I can still open them and they display fine - but when I upload a zip file that is part of a multi-volume zip, unzipping usually fails for one file inside the zip, while the rest gets unzipped fine.</p>

<p><strong>Example:</strong></p>

<p>In this example, you can see the original file (<code>import_filesystem.kmumitkst.z01.ORIGINAL</code>), which was <code>10485760</code> bytes large, which I posted to my HttpListener and which stored the version named <code>import_filesystem.kmumitkst.z01</code>, which is <code>10485762</code> bytes large.</p>

<p>When I then unzip it via WinRar, it tells me that the CRC/checksum isn't correct and one file in it is corrupt due to these two extra bytes.</p>

<p><a href="https://i.stack.imgur.com/b8W1T.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/b8W1T.png" alt="enter image description here"></a></p>

<p><strong>Code:</strong></p>

<p>This is the code storing the received file:</p>

<pre><code>while (_listener.IsListening)
{
    ThreadPool.QueueUserWorkItem((c) =&gt;
    {
        var ctx = c as HttpListenerContext;  
        SaveFile(ctx.Request.ContentEncoding, GetBoundary(ctx.Request.ContentType), 
            ctx.Request.InputStream, targetFilePath);
        ...
    }
}

// =====================================


private static void SaveFile(Encoding enc, String boundary, Stream input, string targetPath)
{
    Byte[] boundaryBytes = enc.GetBytes(boundary);
    Int32 boundaryLen = boundaryBytes.Length;

    using (FileStream output = new FileStream(targetPath, FileMode.Create, FileAccess.Write))
    {
        Byte[] buffer = new Byte[1024];
        Int32 len = input.Read(buffer, 0, 1024);
        Int32 startPos = -1;

        // Find start boundary
        while (true)
        {
            if (len == 0)
            {
                throw new Exception("Start Boundaray Not Found");
            }

            startPos = IndexOf(buffer, len, boundaryBytes);
            if (startPos &gt;= 0)
            {
                break;
            }
            else
            {
                Array.Copy(buffer, len - boundaryLen, buffer, 0, boundaryLen);
                len = input.Read(buffer, boundaryLen, 1024 - boundaryLen);
            }
        }

        // Skip four lines (Boundary, Content-Disposition, Content-Type, and a blank)
        for (Int32 i = 0; i &lt; 4; i++)
        {
            while (true)
            {
                if (len == 0)
                {
                    throw new Exception("Preamble not Found.");
                }

                startPos = Array.IndexOf(buffer, enc.GetBytes("\n")[0], startPos);
                if (startPos &gt;= 0)
                {
                    startPos++;
                    break;
                }
                else
                {
                    len = input.Read(buffer, 0, 1024);
                }
            }
        }

        Array.Copy(buffer, startPos, buffer, 0, len - startPos);
        len = len - startPos;

        while (true)
        {
            Int32 endPos = IndexOf(buffer, len, boundaryBytes);
            if (endPos &gt;= 0)
            {
                if (endPos &gt; 0) output.Write(buffer, 0, endPos);
                break;
            }
            else if (len &lt;= boundaryLen)
            {
                throw new Exception("End Boundaray Not Found");
            }
            else
            {
                output.Write(buffer, 0, len - boundaryLen);
                Array.Copy(buffer, len - boundaryLen, buffer, 0, boundaryLen);
                len = input.Read(buffer, boundaryLen, 1024 - boundaryLen) + boundaryLen;
            }
        }
    }
}

private static String GetBoundary(String ctype)
{
    return "--" + ctype.Split(';')[1].Split('=')[1];
}

private static Int32 IndexOf(Byte[] buffer, Int32 len, Byte[] boundaryBytes)
{
    for (Int32 i = 0; i &lt;= len - boundaryBytes.Length; i++)
    {
        Boolean match = true;
        for (Int32 j = 0; j &lt; boundaryBytes.Length &amp;&amp; match; j++)
        {
            match = buffer[i + j] == boundaryBytes[j];
        }

        if (match)
        {
            return i;
        }
    }
    return -1;
}
</code></pre>

<p><strong>Question:</strong></p>

<p>Where do these two extra bytes come from? Regardless of what kind of file or file size I sent, it's always exactly 2 bytes too much.</p>

<p>Is there any other way to save a received file through the <code>HttpListener</code>? Thanks for any hint.</p>