C# 使用HttpListener发送图像仅适用于某些图像

C# 使用HttpListener发送图像仅适用于某些图像,c#,httplistener,C#,Httplistener,我正在尝试创建一个小型http代理服务。这不太好用。它能够提供HTML okayish,但是它会被图像阻塞。也就是说,一些图像 通过我的代理发送url会在响应中产生19.4KB(根据firebug) 根据firebug的说法,直接访问该url也会产生19.4KB的响应。不同的是,当我把它放到我的代理中时,它不会显示,但是当我直接浏览时它会显示 一个完全不同的url很好用。有人知道吗 private void DoProxy() { var http = listener.GetConte

我正在尝试创建一个小型http代理服务。这不太好用。它能够提供HTML okayish,但是它会被图像阻塞。也就是说,一些图像

通过我的代理发送url会在响应中产生19.4KB(根据firebug) 根据firebug的说法,直接访问该url也会产生19.4KB的响应。不同的是,当我把它放到我的代理中时,它不会显示,但是当我直接浏览时它会显示

一个完全不同的url很好用。有人知道吗

private void DoProxy()
{
    var http = listener.GetContext();
    string url = http.Request.QueryString["url"];
    WebRequest request = HttpWebRequest.Create(url);
    WebResponse response = request.GetResponse();
    http.Response.ContentType = response.ContentType;

    byte[] content;
    using (Stream responseStream = response.GetResponseStream())
        content = ReadAll(responseStream);
    http.Response.ContentLength64 = content.Length;
    http.Response.OutputStream.Write(content, 0, content.Length);
    http.Response.Close();
}

private byte[] ReadAll(Stream stream)
{
    IList<byte> array = new List<byte>();
    int b;
    while ((b = stream.ReadByte()) != -1)
        array.Add(Convert.ToByte(b));
    return array.ToArray();
}
private void DoProxy()
{
var http=listener.GetContext();
字符串url=http.Request.QueryString[“url”];
WebRequest=HttpWebRequest.Create(url);
WebResponse=request.GetResponse();
http.Response.ContentType=Response.ContentType;
字节[]内容;
使用(Stream responseStream=response.GetResponseStream())
内容=ReadAll(responseStream);
http.Response.ContentLength64=content.Length;
http.Response.OutputStream.Write(content,0,content.Length);
http.Response.Close();
}
专用字节[]ReadAll(流)
{
IList数组=新列表();
int b;
而((b=stream.ReadByte())!=-1)
Add(Convert.ToByte(b));
返回array.ToArray();
}
您可以尝试替换

http.Response.Close();


问题可能是您没有指定响应的MIME类型。浏览器这些日子是非常宽容的,但也许有一种情况,浏览器不知道如何处理你从它喉咙里伸出来的东西


我编写了最小型的基于文件的http服务器,据我记忆所及,它可以毫无问题地提供图像。

在关闭响应之前,我会尝试刷新/关闭
输出流

另外,作为第二个建议,请查看来自原始站点的HTTP流量,然后使用HTTP调试器通过代理站点,如-使用代理时一定会有所不同

另外,为了使ReadAll方法更有效,通常我会避免将全部内容加载到内存中,因为这会导致巨大的文件爆炸——只需将它们直接从输入流流传输到输出流。如果仍想使用字节数组,请考虑以下(未经测试但应工作):

private byte[]ReadAll(流)
{
字节[]缓冲区=新字节[8192];
int字节读取=1;
List arrayList=新列表();
而(字节读取>0)
{
bytesRead=stream.Read(buffer,0,buffer.Length);
AddRange(新的ArraySegment(缓冲区,0,字节读取).Array);
}
返回arrayList.ToArray();
}

只需将文本响应和图像响应分开,并分别写入输出。我确实喜欢下面的内容,它对我很有用

static void Main(string[] args)
    {
        HttpListener server = new HttpListener();
        server.Prefixes.Add("http://localhost:9020/");
        server.Start();
        Console.WriteLine("Listening...");
        while (true)
        {
            try
            { 
            HttpListenerContext context = server.GetContext();
            HttpListenerResponse response = context.Response;
            String localpath = context.Request.Url.LocalPath;
            string page = Directory.GetCurrentDirectory() + localpath;
            string msg = "";
            bool imgtest = false;
            if (localpath == "/")
              page = "index.html";
            Console.WriteLine(localpath);
            if (!page.Contains("jpg") && !page.Contains("png"))//Separates image request
            { 
               TextReader tr = new StreamReader(page);
               msg = tr.ReadToEnd();
               tr.Dispose();
            }
            else
            {
               byte[] output = File.ReadAllBytes(page);
               response.ContentLength64 = output.Length;
               Stream st1 = response.OutputStream;
               st1.Write(output, 0, output.Length);
               imgtest = true;
            }
            if (imgtest==false)
            { 
               byte[] buffer = Encoding.UTF8.GetBytes(msg);
               response.ContentLength64 = buffer.Length;
               Stream st = response.OutputStream;
               st.Write(buffer, 0, buffer.Length);
               context.Response.Close();
            }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error:  "+ex);
                Console.ReadKey();
            }
        }

作为旁注-您不应该一次读取一个字节的ReadAll来读取原始流,这是非常无效的。在关闭前,我会尝试刷新/关闭
OutputStream
response@BrokenGlass嗯,要不然我怎么做呢?标题中不保证提供内容长度。读取方法需要一个数组和一个读取计数-如果请求-响应大于我选择的缓冲区大小,则调整/更改数组会很麻烦?下面添加了一个响应来解决此问题谢谢您的回答!实际上做了一些实验,做了一些类似于你的阅读方法的事情,发现它是这样工作的,但不是第一次!一定是漏了字节什么的,奇怪的。无论如何,谢谢!根据您的建议,我只使用了responseStream.CopyTo(Http.Response.OutputStream)。非常简单,而且有效。:)
private byte[] ReadAll(Stream stream)
{
    byte[] buffer = new byte[8192];
    int bytesRead = 1;
    List<byte> arrayList = new List<byte>();

    while (bytesRead > 0)
    {
        bytesRead = stream.Read(buffer, 0, buffer.Length);
        arrayList.AddRange(new ArraySegment<byte>(buffer, 0, bytesRead).Array);
    }
    return arrayList.ToArray();
}
static void Main(string[] args)
    {
        HttpListener server = new HttpListener();
        server.Prefixes.Add("http://localhost:9020/");
        server.Start();
        Console.WriteLine("Listening...");
        while (true)
        {
            try
            { 
            HttpListenerContext context = server.GetContext();
            HttpListenerResponse response = context.Response;
            String localpath = context.Request.Url.LocalPath;
            string page = Directory.GetCurrentDirectory() + localpath;
            string msg = "";
            bool imgtest = false;
            if (localpath == "/")
              page = "index.html";
            Console.WriteLine(localpath);
            if (!page.Contains("jpg") && !page.Contains("png"))//Separates image request
            { 
               TextReader tr = new StreamReader(page);
               msg = tr.ReadToEnd();
               tr.Dispose();
            }
            else
            {
               byte[] output = File.ReadAllBytes(page);
               response.ContentLength64 = output.Length;
               Stream st1 = response.OutputStream;
               st1.Write(output, 0, output.Length);
               imgtest = true;
            }
            if (imgtest==false)
            { 
               byte[] buffer = Encoding.UTF8.GetBytes(msg);
               response.ContentLength64 = buffer.Length;
               Stream st = response.OutputStream;
               st.Write(buffer, 0, buffer.Length);
               context.Response.Close();
            }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error:  "+ex);
                Console.ReadKey();
            }
        }