C# HttpListener:存储发布的文件总是比原始文件大 2 个字节
C# HttpListener: storing posted file is always 2 byte larger than original
问题描述:
我的 C# 程序中有一个 HttpListener
,它接受带有已发布文件(jpg、doc、zip 或类似文件)的 POST 请求。我在同一台 Windows 机器上发送和接收文件。
我从
(来自Java世界,我是C#/.Net新手),据说只是一个概念验证,在服务器端上传和存储数据几乎可以正常工作,除了 存储的文件总是比原始文件大 2 个字节。
这对于 jpg、doc 或单个 zip 文件无关紧要 - 我仍然可以打开它们并且它们显示正常 - 但是当我上传一个属于多卷 zip 的 zip 文件时,解压通常会失败zip 中的文件,而其余的则可以很好地解压缩。
示例:
在此示例中,您可以看到原始文件 (import_filesystem.kmumitkst.z01.ORIGINAL
),它有 10485760
字节大,我将其发布到我的 HttpListener 并存储了名为 import_filesystem.kmumitkst.z01
的版本,这是 10485762
字节大。
然后当我通过 WinRar 解压缩它时,它告诉我 CRC/checksum 不正确并且其中的一个文件由于这两个额外的字节而损坏。
代码:
这是存储接收到的文件的代码:
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem((c) =>
{
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 >= 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 < 4; i++)
{
while (true)
{
if (len == 0)
{
throw new Exception("Preamble not Found.");
}
startPos = Array.IndexOf(buffer, enc.GetBytes("\n")[0], startPos);
if (startPos >= 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 >= 0)
{
if (endPos > 0) output.Write(buffer, 0, endPos);
break;
}
else if (len <= 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 <= len - boundaryBytes.Length; i++)
{
Boolean match = true;
for (Int32 j = 0; j < boundaryBytes.Length && match; j++)
{
match = buffer[i + j] == boundaryBytes[j];
}
if (match)
{
return i;
}
}
return -1;
}
问题:
这两个额外的字节是从哪里来的?无论我发送何种文件或文件大小,它总是多出 2 个字节。
有没有其他方法可以通过HttpListener
保存接收到的文件?感谢您的任何提示。
找到解决方案,不得不改变
while (true)
{
Int32 endPos = IndexOf(buffer, len, boundaryBytes);
if (endPos >= 0)
{
if (endPos > 0) output.Write(buffer, 0, endPos);
break;
}
到
while (true)
{
Int32 endPos = IndexOf(buffer, len, boundaryBytes);
if (endPos >= 0)
{
if (endPos > 0) output.Write(buffer, 0, endPos-2);
break;
}
在 endPos
中添加一个 -2
,以避免在末尾出现额外的换行符。
问题描述:
我的 C# 程序中有一个 HttpListener
,它接受带有已发布文件(jpg、doc、zip 或类似文件)的 POST 请求。我在同一台 Windows 机器上发送和接收文件。
我从 (来自Java世界,我是C#/.Net新手),据说只是一个概念验证,在服务器端上传和存储数据几乎可以正常工作,除了 存储的文件总是比原始文件大 2 个字节。
这对于 jpg、doc 或单个 zip 文件无关紧要 - 我仍然可以打开它们并且它们显示正常 - 但是当我上传一个属于多卷 zip 的 zip 文件时,解压通常会失败zip 中的文件,而其余的则可以很好地解压缩。
示例:
在此示例中,您可以看到原始文件 (import_filesystem.kmumitkst.z01.ORIGINAL
),它有 10485760
字节大,我将其发布到我的 HttpListener 并存储了名为 import_filesystem.kmumitkst.z01
的版本,这是 10485762
字节大。
然后当我通过 WinRar 解压缩它时,它告诉我 CRC/checksum 不正确并且其中的一个文件由于这两个额外的字节而损坏。
代码:
这是存储接收到的文件的代码:
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem((c) =>
{
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 >= 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 < 4; i++)
{
while (true)
{
if (len == 0)
{
throw new Exception("Preamble not Found.");
}
startPos = Array.IndexOf(buffer, enc.GetBytes("\n")[0], startPos);
if (startPos >= 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 >= 0)
{
if (endPos > 0) output.Write(buffer, 0, endPos);
break;
}
else if (len <= 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 <= len - boundaryBytes.Length; i++)
{
Boolean match = true;
for (Int32 j = 0; j < boundaryBytes.Length && match; j++)
{
match = buffer[i + j] == boundaryBytes[j];
}
if (match)
{
return i;
}
}
return -1;
}
问题:
这两个额外的字节是从哪里来的?无论我发送何种文件或文件大小,它总是多出 2 个字节。
有没有其他方法可以通过HttpListener
保存接收到的文件?感谢您的任何提示。
找到解决方案,不得不改变
while (true)
{
Int32 endPos = IndexOf(buffer, len, boundaryBytes);
if (endPos >= 0)
{
if (endPos > 0) output.Write(buffer, 0, endPos);
break;
}
到
while (true)
{
Int32 endPos = IndexOf(buffer, len, boundaryBytes);
if (endPos >= 0)
{
if (endPos > 0) output.Write(buffer, 0, endPos-2);
break;
}
在 endPos
中添加一个 -2
,以避免在末尾出现额外的换行符。