ASp.Net Mvc 1.0 动态图像从控制器返回需要 154 秒+快速、轻松地在 IE8、firefox 和所有其他浏览器中显示
我对 IE、IIS 6.0 动态 PNG 文件有一个奇怪的问题,我对如何修复感到困惑。
来自 Helper 的片段(这会将 URL 返回到视图,以从我的控制器请求图像。
string url = LinkBuilder.BuildUrlFromExpression( helper.ViewContext.RequestContext, helper.RouteCollection, c => c.FixHeight(ir.Filename, ir.AltText, "FFFFFF")); url = url.Replace("&", "&"); sb.Append(string.Format("<已删除 id=\"TheImage\" src=\"{0}\" alt=\"\" />", url)+Environment .NewLine);
这会生成一段 html,如下所示:- img id="TheImage" src="/ImgText/FixHeight?sFile=Images%2FUser%2FJulianGuppy%2FMediums%2Fconservatory.jpg&backgroundColour=FFFFFF" alt="" /
括号丢失,因为我无法发布图像......即使我不想发布图像,我只想发布标记... 叹息
来自控制器 ImgTextController 的片段
/// <summary>
/// This function fixes the height of the image
/// </summary>
/// <param name="sFile"></param>
/// <param name="alternateText"></param>
/// <param name="backgroundColour"></param>
/// <returns></returns>
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult FixHeight(string sFile, string alternateText, string backgroundColour)
{
#region File
if (string.IsNullOrEmpty(sFile))
{
return new ImgTextResult();
}
// MVC specific change to prepend the new directory
if (sFile.IndexOf("Content") == -1)
{
sFile = "~/Content/" + sFile;
}
// open the file
System.Drawing.Image img;
try
{
img = System.Drawing.Image.FromFile(Server.MapPath(sFile));
}
catch
{
img = null;
}
// did we fail?
if (img == null)
{
return new ImgTextResult();
}
#endregion File
#region Width
// Sort out the width from the image passed to me
Int32 nWidth = img.Width;
#endregion Width
#region Height
Int32 nHeight = img.Height;
#endregion Height
// What is the ideal height given a width of 2100 this should be 1400.
var nIdealHeight = (int)(nWidth / 1.40920096852);
// So is the actual height of the image already greater than the ideal height?
Int32 nSplit;
if (nIdealHeight < nHeight)
{
// Yes, do nothing, well i need to return the iamge...
nSplit = 0;
}
else
{
// rob wants to not show the white at the top or bottom, so if we were to crop the image how would be do it
// 1. Calculate what the width should be If we dont adjust the heigt
var newIdealWidth = (int)(nHeight * 1.40920096852);
// 2. This newIdealWidth should be smaller than the existing width... so work out the split on that
Int32 newSplit = (nWidth - newIdealWidth) / 2;
// 3. Now recrop the image using 0-nHeight as the height (i.e. full height)
// but crop the sides so that its the correct aspect ration
var newRect = new Rectangle(newSplit, 0, newIdealWidth, nHeight);
img = CropImage(img, newRect);
nHeight = img.Height;
nWidth = img.Width;
nSplit = 0;
}
// No, so I want to place this image on a larger canvas and we do this by Creating a new image to be the size that we want
System.Drawing.Image canvas = new Bitmap(nWidth, nIdealHeight, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(canvas);
#region Color
// Whilst we can set the background colour we shall default to white
if (string.IsNullOrEmpty(backgroundColour))
{
backgroundColour = "FFFFFF";
}
Color bc = ColorTranslator.FromHtml("#" + backgroundColour);
#endregion Color
// Filling the background (which gives us our broder)
Brush backgroundBrush = new SolidBrush(bc);
g.FillRectangle(backgroundBrush, -1, -1, nWidth + 1, nIdealHeight + 1);
// draw the image at the position
var rect = new Rectangle(0, nSplit, nWidth, nHeight);
g.DrawImage(img, rect);
return new ImgTextResult { Image = canvas, ImageFormat = ImageFormat.Png };
}
我的 ImgTextResult 是一个为我返回操作结果的类,但将图像从内存流嵌入到响应.输出流。
,
/// <summary>
/// Execute the result
/// </summary>
/// <param name="context"></param>
public override void ExecuteResult(ControllerContext context)
{
// output
context.HttpContext.Response.Clear();
context.HttpContext.Response.ContentType = "image/png";
try
{
var memStream = new MemoryStream();
Image.Save(memStream, ImageFormat.Png);
context.HttpContext.Response.BinaryWrite(memStream.ToArray());
context.HttpContext.Response.Flush();
context.HttpContext.Response.Close();
memStream.Dispose();
Image.Dispose();
}
catch (Exception ex)
{
string a = ex.Message;
}
}
现在,所有这些都可以在本地运行并且非常可爱,而且实际上所有这些都可以在我的生产服务器上运行
但仅适用于 Firefox、Safari、Chrome(和其他浏览器)IE 适合并决定它要么不会显示图像,要么它确实在大约 154 秒的等待后显示图像......
我已确保我的 HTML 符合 XHTML 标准,我已确保服务器上的事件日志中没有路由错误或崩溃......
现在显然我一直是一个布偶,做了一些错事...但我无法理解的是为什么在开发中一切正常,在生产中所有非 IE 浏览器也工作正常,但使用 IIS 6.0 生产服务器的 IE 8 有某种问题返回此 PNG 时出现问题,并且我没有可跟踪的错误...所以我正在寻找的是有关如何调试此问题的指导。
I have a curious problem with IE, IIS 6.0 dynamic PNG files and I am baffled as to how to fix..
Snippet from Helper (this returns the URL to the view for requesting the images from my Controller.
string url = LinkBuilder.BuildUrlFromExpression(helper.ViewContext.RequestContext, helper.RouteCollection, c => c.FixHeight(ir.Filename, ir.AltText, "FFFFFF"));
url = url.Replace("&", "&");
sb.Append(string.Format("<removed id=\"TheImage\" src=\"{0}\" alt=\"\" />", url)+Environment.NewLine);
This produces a piece of html as follows:-
img id="TheImage" src="/ImgText/FixHeight?sFile=Images%2FUser%2FJulianGuppy%2FMediums%2Fconservatory.jpg&backgroundColour=FFFFFF" alt="" /
brackets missing because i cant post an image... even though I dont want to post an image I jsut want to post the markup... sigh
Snippet from Controller ImgTextController
/// <summary>
/// This function fixes the height of the image
/// </summary>
/// <param name="sFile"></param>
/// <param name="alternateText"></param>
/// <param name="backgroundColour"></param>
/// <returns></returns>
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult FixHeight(string sFile, string alternateText, string backgroundColour)
{
#region File
if (string.IsNullOrEmpty(sFile))
{
return new ImgTextResult();
}
// MVC specific change to prepend the new directory
if (sFile.IndexOf("Content") == -1)
{
sFile = "~/Content/" + sFile;
}
// open the file
System.Drawing.Image img;
try
{
img = System.Drawing.Image.FromFile(Server.MapPath(sFile));
}
catch
{
img = null;
}
// did we fail?
if (img == null)
{
return new ImgTextResult();
}
#endregion File
#region Width
// Sort out the width from the image passed to me
Int32 nWidth = img.Width;
#endregion Width
#region Height
Int32 nHeight = img.Height;
#endregion Height
// What is the ideal height given a width of 2100 this should be 1400.
var nIdealHeight = (int)(nWidth / 1.40920096852);
// So is the actual height of the image already greater than the ideal height?
Int32 nSplit;
if (nIdealHeight < nHeight)
{
// Yes, do nothing, well i need to return the iamge...
nSplit = 0;
}
else
{
// rob wants to not show the white at the top or bottom, so if we were to crop the image how would be do it
// 1. Calculate what the width should be If we dont adjust the heigt
var newIdealWidth = (int)(nHeight * 1.40920096852);
// 2. This newIdealWidth should be smaller than the existing width... so work out the split on that
Int32 newSplit = (nWidth - newIdealWidth) / 2;
// 3. Now recrop the image using 0-nHeight as the height (i.e. full height)
// but crop the sides so that its the correct aspect ration
var newRect = new Rectangle(newSplit, 0, newIdealWidth, nHeight);
img = CropImage(img, newRect);
nHeight = img.Height;
nWidth = img.Width;
nSplit = 0;
}
// No, so I want to place this image on a larger canvas and we do this by Creating a new image to be the size that we want
System.Drawing.Image canvas = new Bitmap(nWidth, nIdealHeight, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(canvas);
#region Color
// Whilst we can set the background colour we shall default to white
if (string.IsNullOrEmpty(backgroundColour))
{
backgroundColour = "FFFFFF";
}
Color bc = ColorTranslator.FromHtml("#" + backgroundColour);
#endregion Color
// Filling the background (which gives us our broder)
Brush backgroundBrush = new SolidBrush(bc);
g.FillRectangle(backgroundBrush, -1, -1, nWidth + 1, nIdealHeight + 1);
// draw the image at the position
var rect = new Rectangle(0, nSplit, nWidth, nHeight);
g.DrawImage(img, rect);
return new ImgTextResult { Image = canvas, ImageFormat = ImageFormat.Png };
}
My ImgTextResult is a class that returns an Action result for me but embedding the image from a memory stream into the response.outputstream.
snippet from my ImageResults
/// <summary>
/// Execute the result
/// </summary>
/// <param name="context"></param>
public override void ExecuteResult(ControllerContext context)
{
// output
context.HttpContext.Response.Clear();
context.HttpContext.Response.ContentType = "image/png";
try
{
var memStream = new MemoryStream();
Image.Save(memStream, ImageFormat.Png);
context.HttpContext.Response.BinaryWrite(memStream.ToArray());
context.HttpContext.Response.Flush();
context.HttpContext.Response.Close();
memStream.Dispose();
Image.Dispose();
}
catch (Exception ex)
{
string a = ex.Message;
}
}
Now all of this works locally and lovely, and indeed all of this works on my production server
BUT Only for Firefox, Safari, Chrome (and other browsers) IE has a fit and decides that it either wont display the image or it does display the image after approx 154seconds of waiting.....
I have made sure my HTML is XHTML compliant, I have made sure I am getting no Routing errors or crashes in my event log on the server....
Now obviously I have been a muppet and have done something wrong... but what I cant fathom is why in development all works fine, and in production all non IE browsers also work fine, but IE 8 using IIS 6.0 production server is having some kind of problem in returning this PNG and I dont have an error to trace... so what I am looking for is guidance as to how I can debug this problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看起来可能是时候安装 Fiddler 或 HttpWatch 并了解发生了什么情况。
Looks like it might be time to install Fiddler or HttpWatch and find out what is going on.
好吧,我想做的是转换我的图像(jpg、bmp 等......并将它们返回为 png) - 然而。尽管所有其他浏览器都会接受编码并正常显示它们,但 IE 决定隐藏 png 图像(部分显示后),因为它认为它不是 PNG 图像。 (尽管如此)所以我放弃了转换方法,只是以原始格式返回图像。 ---
如果有人想出一种可靠地将任何图像格式转换为 png 的方法,以便我可以从内存流动态返回它,那么请告诉我......
所以我现在关闭它,因为 IE 已经关闭了赢得了这场战斗——
我希望 IE 赶紧滚蛋然后死掉。我非常讨厌IE。说真的,它只是吸死人睾丸的汗水。
Well, what I wanted to do was to convert my images (jpg, bmp, etc... and return them as png) - however. Although all other browsers would accept the encoding and display them fine, IE decided to hide the png image (after partially displaying it) because it thought it wasn't a PNG image. (Even though it was) So I gave up with the conversion methods and just returned the image in its original format. ---
if anybody comes up with a way of reliably converting any image format into png so that I can return it dynamically from a memory stream, then please do let me know....
So I am closing this for now as IE has won this battle -
I wish IE would just sod off and die. I hate IE so much. Seriously it just sucks the sweat of a dead mans balls.
永远不要调用 Response.End()
至少,这就是 HttpResponse 文档的维护者说。
Response.End() 结束 http 连接,通常会孤立服务器缓冲区或流中某处的数据。最好让 IIS 结束连接(或重用它),因为许多客户端没有完美的网络堆栈。
IE 有一个糟糕的网络堆栈(任何使用过 FF 的 IETab 的人都可以见证,当放置在 FF 网络管道之上时,IE 几乎很快)。其他浏览器可以更好地处理快速关闭的连接,因此可能不会对关闭的连接做出糟糕的响应。
在另一个主题上,看起来您正在重新发明轮子。它也不是一个容易正确构建的轮子。
根据我看到的代码,看起来您正在泄漏 GDI 位图“img”,如果请求期间发生任何意外情况,则会发生额外的泄漏。请注意,.NET 无法正确处理 GDI 垃圾收集,这是服务器崩溃的最大原因之一 - 请确保修复该问题,我的朋友:)
Never call Response.End()
At least, that's what the maintainer for the HttpResponse documentation says.
Response.End() ends the http connection, often orphaning data in the server's buffer or somewhere in the stream. It's better to let IIS end the connection (or reuse it) instead, since many clients don't have a perfect network stack.
IE has a terrible network stack (as anyone who has used IETab for FF can witness, IE is almost fast when placed on top of the FF network pipe). The other browsers handle the quickly closed connection much better, and so probably aren't responding badly to the closed connection.
On a different topic, it looks like you are re-inventing the wheel. It's not an easy wheel to build properly, either.
Based on the code I see, it looks like you are leaking the GDI bitmap 'img', and additional leaks would occur if anything unexpected happened during the request. Note that .NET does not garbage collection GDI handles properly, and it's one of the biggest causes of server crashes - make sure you get that fixed, my friend :)