3

所以,我写了一个小Webserver。首先,我尝试只发送文本,但现在我也在尝试发送图片。(或包含图片的 html 页面)

这是我尝试过的:

if ((Path.GetExtension(filename).ToLower() == "jpg") || (Path.GetExtension(filename).ToLower() == "png") || (Path.GetExtension(filename).ToLower() == "gif"))
{
    Image image = Image.FromFile(filename);
    MemoryStream ms = new MemoryStream();
    image.Save(ms, image.RawFormat);
    responseContent = Encoding.Default.GetString(ms.ToArray());
    responseheader = "HTTP/1.1 200 OK\r\n" +
                     "Server: MiniWebServer\r\n" +
                     "Content-Length: " + responseContent.Length + "\r\n" +
                     "Content-Language: de\r\n" +
                     "Connection: close\r\n\r\n"; 
}

finalResponse = responseheader + responseContent;
return Encoding.ASCII.GetBytes(finalResponse);

因此,我尝试在浏览器中打开 html 文件(其中包含图片),但它没有显示出来。然后,我尝试只在浏览器中打开图片,但随后出现一个错误,表示无法显示图形,因为它包含错误。

4

1 回答 1

4

您将所有内容编码为字符串。

对于 HTTP 标头,这很好,因为所有浏览器都希望以这种方式读取标头,并且必须像现在一样使用 ASCII 对其进行编码。

如果您发送文本,也可以,因为当您不指定内容类型时,大多数浏览器默认为 ASCII 模式。

但是对于图像和其他数据,您的响应中必须发生以下情况。

设置Content Type标头,指定您要发送的内容的类型。例子是

内容类型:图片/gif

或者

内容类型:图片/png

现在浏览器(或接收内容的任何东西)知道会发生什么。除了,您以 ASCII 编码对图像进行了编码。

ASCII 仅用于将简单测试编码为字节。(我说很简单,因为 ASCII 只支持很少的字符集。它不支持多语言等。Unicode、UTF 和其他一些编码支持。)

这会导致 ASCII 将您的图像作为文本读取,并删除或损坏它不理解的字母。(这是您的大部分图像数据。)

您要做的是,以您在标头中指定的格式发送其余的响应(图像,在标头之后)Content-Type。只需发送ms.ToArray调用的结果。

理想情况下,您将确保图像采用您指定的正确格式,并且不依赖于文件扩展名,但实际上,许多服务器会谎报内容类型并指定image/*并让浏览器弄清楚。

这是一个关于如何在 C# 中构建 Web 服务器的好例子。

希望这可以帮助。


附带说明一下,您的实现不擅长的是内存消耗。您正在使用内存流将整个图像加载到内存中,然后将其复制到数组中。这是每个请求在内存中的 2 个图像副本。我不确定你想要多少可扩展性。但是,如果您同时收到 10 个高分辨率图像的请求(比如 5 MB,对于 8MP 相机拍摄的典型照片?),现在您的服务器突然将 100 MB 的数据加载到内存中。

如果您从用户接受文件并在写入文件之前将它们加载到内存中,这可能会成为一个更大的问题。如果用户决定上传 1 GB 的文件,它将关闭您的服务器。(我在一些用 ASP.NET 编写的站点中看到了这种情况,它非常糟糕。故障部分是 ASP.NET 的优化。)

您可以做的是打开一个文件流,并将字节复制到响应中而不加载整个图像。上面的链接显示了此代码。

于 2012-11-04T03:22:59.867 回答