C# HttpListener如何为图像提供服务
我正在制作一个简单的Web服务器来提供html、css、js和图像(用c#完成)。我正在使用HttpListener,我可以让html、javascript和css文件正常工作。我只是在图像方面有点问题。这是我目前正在使用的:C# HttpListener如何为图像提供服务,c#,httplistener,httplistenerrequest,C#,Httplistener,Httplistenerrequest,我正在制作一个简单的Web服务器来提供html、css、js和图像(用c#完成)。我正在使用HttpListener,我可以让html、javascript和css文件正常工作。我只是在图像方面有点问题。这是我目前正在使用的: if (request.RawUrl.ToLower().Contains(".png") || request.RawUrl.Contains(".ico") || request.RawUrl.ToLower().Contains(".jpg") ||
if (request.RawUrl.ToLower().Contains(".png") || request.RawUrl.Contains(".ico") || request.RawUrl.ToLower().Contains(".jpg") || request.RawUrl.ToLower().Contains(".jpeg"))
{
string dir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string[] img = request.RawUrl.Split('/');
string path = dir + @"\public\imgs\" + img[img.Length - 1];
FileInfo fileInfo = new FileInfo(path);
long numBytes = fileInfo.Length;
FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader binaryReader = new BinaryReader(fileStream);
byte[] output = binaryReader.ReadBytes((int)numBytes);
binaryReader.Close();
fileStream.Close();
var temp = System.Text.Encoding.UTF8.GetString(output);
return temp;
}
我正在将图像转换为字符串以返回它们(这是我老板建议的方式)。这就是我处理这些请求的方法
private static string SendResponse(HttpListenerRequest request)
这是我的WebServer类Run()方法。对SetContentType的调用只是通过request.RawUrl确定内容类型
public void Run()
{
ThreadPool.QueueUserWorkItem((o) =>
{
Console.WriteLine("StackLight Web Server is running...");
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem((c) =>
{
var ctx = c as HttpListenerContext;
try
{
// store html content in a byte array
string responderString = _responderMethod(ctx.Request);
// set the content type
ctx.Response.Headers[HttpResponseHeader.ContentType] = SetContentType(ctx.Request.RawUrl);
byte[] buffer = buffer = Encoding.UTF8.GetBytes(responderString);
// this writes the html out from the byte array
ctx.Response.ContentLength64 = buffer.Length;
using(Stream stream = ctx.Response.OutputStream)
{
stream.Write(buffer, 0, buffer.Length);
}
}
catch (Exception ex)
{
ConfigLogger.Instance.LogCritical(LogCategory, ex);
}
}, _listener.GetContext());
}
}
catch (Exception ex)
{
ConfigLogger.Instance.LogCritical(LogCategory, ex);
}
});
}
我的html页面需要在屏幕上显示一个图像,到目前为止,它显示了一个损坏的图像。我知道图像目录是正确的,我已经测试过了
这是我获得Web服务器代码的地方:
我在想,也许我必须更改SendResponse方法以不返回字符串这里有些非常糟糕的东西:
ctx
。我不明白你为什么需要手动挡块。使用使用
路径
。我可以通过导航到/img/.\..\web.config
(类似的内容)来请求您的web.config文件考虑将一些常用表达式分解为变量。您的
ToLower
出现复制粘贴错误。不要做肮脏的事,你会有更少的臭虫。我想出来了。我创建了一个类来保存数据、内容类型和request.RawUrl。然后,在传递字符串的地方,我将其更改为传递我创建的对象
因此,对于我的WebServer类,我的Run方法如下所示:
public void Run()
{
ThreadPool.QueueUserWorkItem((o) =>
{
Console.WriteLine("StackLight Web Server is running...");
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem((c) =>
{
var ctx = c as HttpListenerContext;
try
{
// set the content type
ctx.Response.Headers[HttpResponseHeader.ContentType] = SetContentType(ctx.Request.RawUrl);
WebServerRequestData data = new WebServerRequestData();
// store html content in a byte array
data = _responderMethod(ctx.Request);
string res = "";
if(data.ContentType.Contains("text"))
{
char[] chars = new char[data.Content.Length/sizeof(char)];
System.Buffer.BlockCopy(data.Content, 0, chars, 0, data.Content.Length);
res = new string(chars);
data.Content = Encoding.UTF8.GetBytes(res);
}
// this writes the html out from the byte array
ctx.Response.ContentLength64 = data.Content.Length;
ctx.Response.OutputStream.Write(data.Content, 0, data.Content.Length);
}
catch (Exception ex)
{
ConfigLogger.Instance.LogCritical(LogCategory, ex);
}
finally
{
ctx.Response.OutputStream.Close();
}
}, _listener.GetContext());
}
}
catch (Exception ex)
{
ConfigLogger.Instance.LogCritical(LogCategory, ex);
}
});
}
我的SendResponse方法如下所示:
private static WebServerRequestData SendResponse(HttpListenerRequest request)
{
string dir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string[] fileUrl = request.RawUrl.Split('/');
// routes
if (request.RawUrl.Contains("/"))
{
// this is the main page ('/'), all other routes can be accessed from here (including css, js, & images)
if (request.RawUrl.ToLower().Contains(".png") || request.RawUrl.ToLower().Contains(".ico") || request.RawUrl.ToLower().Contains(".jpg") || request.RawUrl.ToLower().Contains(".jpeg"))
{
try
{
string path = dir + Properties.Settings.Default.ImagesPath + fileUrl[fileUrl.Length - 1];
FileInfo fileInfo = new FileInfo(path);
path = dir + @"\public\imgs\" + fileInfo.Name;
byte[] output = File.ReadAllBytes(path);
_data = new WebServerRequestData() {Content = output, ContentType = "image/png", RawUrl = request.RawUrl};
//var temp = System.Text.Encoding.UTF8.GetString(output);
//return Convert.ToBase64String(output);
return _data;
}
catch(Exception ex)
{
ConfigLogger.Instance.LogError(LogCategory, "File could not be read.");
ConfigLogger.Instance.LogCritical(LogCategory, ex);
_errorString = string.Format("<html><head><title>Test</title></head><body>There was an error processing your request:<br />{0}</body></html>", ex.Message);
_byteData = new byte[_errorString.Length * sizeof(char)];
System.Buffer.BlockCopy(_errorString.ToCharArray(), 0, _byteData, 0, _byteData.Length);
_data = new WebServerRequestData() { Content = _byteData, ContentType = "text/html", RawUrl = request.RawUrl };
return _data;
}
}
不能将图像文件任意解码为UTF8字符串,因为该文件的字节不表示UTF8字符串。您可以(1)使用
Convert.ToBase64()
和Convert.FromBase64String()
,或者更好的选择(2)根本不使用字符串-返回文件流
,然后使用CopyTo()
将其直接发送到响应的输出流。我认为问题是因为我返回了一个字符串。因此,我应该将函数的返回类型更改为FileStream?我可以使用convert.ToBase64()使favicon.ico正常工作,但我需要显示的png仍然无法正常工作。我使用“using”修复了空捕获和ctx的处理。我该如何让我的图像显示在我的页面上呢?我不知道该怎么做。我还编辑了我的问题以反映这些变化。我如何防止注入(我想这是一个单独的问题)我需要什么来存储二进制数据?有人建议使用Convert.ToBase64String(),但这仍然是一个字符串。将二进制数据存储在字符串中会产生什么后果?这只是意味着我无法将其转换为图像,对吗?我应该只传递字节数组吗?我在想,我可能应该将SendResponse方法的返回类型从string更改为我将创建的存储内容类型和返回数据的对象。如果要传递和发送字节,请使用包含字节的数据结构。例如,字节[]或流(可能是文件流或内存流)。考虑使用文件。是的,使用封装内容和内容类型的对象是一个好主意。这是很好的面向对象和功能设计。
public class WebServerRequestData
{
public string RawUrl { get; set; }
public string ContentType { get; set; }
public byte[] Content { get; set; }
public string RawData { get; set; }
}