使用Jquery ajax从action方法返回动态图像

时间:2013-09-25 01:10:59

标签: jquery ajax asp.net-mvc asp.net-mvc-3 asp.net-mvc-4

我有一个动作方法,动态生成验证码图像并作为二进制文件返回。在我的视图页面上,我可以在页面加载时显示验证码。我还有一个刷新链接,调用action方法使用$ .ajax获取新的验证码图像,单击时不显示新的验证码图像。 $ .jax调用成功完成,但二进制文件未显示。我想在单击刷新链接时显示新图像而不重新加载整个页面。

我是否遗漏了某些内容,或者是否有另一种方法来调用操作方法而不使用jquery刷新页面。任何帮助,将不胜感激。以下是我的代码

//生成图像的动作方法

public class HomeController : Controller
{
        public FileContentResult CaptchaImage(bool noisy = true)
        {
            var rand = new Random((int)DateTime.Now.Ticks);

            //generate new question
            int a = rand.Next(10, 99);
            int b = rand.Next(0, 9);
            var captcha = string.Format("{0} + {1} = ?", a, b);

            //store answer
            Session["Captcha"] = a + b;

            //image stream
            FileContentResult img = null;

            using (var mem = new MemoryStream())
            using (var bmp = new Bitmap(130, 30))
            using (var gfx = Graphics.FromImage((Image)bmp))
            {
                gfx.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
                gfx.SmoothingMode = SmoothingMode.AntiAlias;
                gfx.FillRectangle(Brushes.White, new Rectangle(0, 0, bmp.Width, bmp.Height));

                //add noise
                if (noisy)
                {
                    int i, r, x, y;
                    var pen = new Pen(Color.Yellow);
                    for (i = 1; i < 10; i++)
                    {
                        pen.Color = Color.FromArgb(
                        (rand.Next(0, 255)),
                        (rand.Next(0, 255)),
                        (rand.Next(0, 255)));

                        r = rand.Next(0, (130 / 3));
                        x = rand.Next(0, 130);
                        y = rand.Next(0, 30);

                        gfx.DrawEllipse(pen, x - r, y - r, r, r);
                    }
                }

                //add question
                gfx.DrawString(captcha, new Font("Tahoma", 15), Brushes.Gray, 2, 3);

                //render as Png
                bmp.Save(mem, System.Drawing.Imaging.ImageFormat.Png);
                img = this.File(mem.GetBuffer(), "image/png");
            }

            return File(img.FileContents, img.ContentType);
        }

}

//查看调用操作方法以显示验证码的页面

<a id="GetCaptcha" href="javascript:void(0)">Refresh</a>
<img id="CaptchaImg" alt="Captcha" src="@Url.Action("CaptchaImage")" style="" />

@section Scripts{
    @Scripts.Render("~/bundles/jqueryval")
    <script>
        $(function () {
            $('#GetCaptcha').click(function () {                

                $.ajax({
                    type: "GET",
                    url:  '@Url.Action("CaptchaImage")', 
                    contentType: "image/png",
                    success: function (data) {
                        alert("Success"); // For testing
                        $('#CaptchaImg').attr('src', "data:image/png;base64," + data);
                    },
                   error: function(error, txtStatus) {
                            console.log(txtStatus);
                            console.log('error');
                        }
                });
            });
        });

    </script>
}

1 个答案:

答案 0 :(得分:0)

action方法没有生成base64编码的字符串,它正在创建一个完整的文件响应。

因此,要刷新验证码图像,您无需更新现有图像上的源,而是创建新的<img src="/home/captchaimage?randomString">元素并用它替换现有的验证码图像。

缓存很可能是一个问题,因此您需要生成一个唯一的字符串以附加到路径,例如随机数或当前日期时间,因此每个请求都是唯一的。

否则,您可以更改action方法以返回base64字符串,然后将视图中的<img src="@Url.Action..更改为<img src="data:image/png;base64,@Html.Action(...或类似内容。