使用Ajax获取二进制数据流图片渲染到img标签

这里我用的是python3.6+Flask。实现一个登录时的验证码,点击通过Ajax的方式获取后台传来的二进制数据

python绘制图片验证码,具体解释都有     Code.py

# -*- encoding:utf8 -*-
import random
import string
from PIL import Image, ImageDraw, ImageFont


# Image:画布   ImageDraw:画笔  ImageFont:画笔的字体
# print(list(string.ascii_letters))
class Captcha(object):
    number = 4  # 生成几位数的验证码
    size = (150, 40)  # 验证码图片的宽度和高度
    fontsize = 35  # 验证码字体大小
    line_number = 2  # 加入干扰线的条数
    SOURCE = list(string.ascii_letters+"123456789")  # 构建一个验证码源文本,包括大小写数字

    # classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,
    # 但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。
    @classmethod
    def __gene_line(cls, draw, width, height):
        # 开始点 X,Y
        begin = (random.randint(0, width), random.randint(0, height))
        # 结束点
        end = (random.randint(0, width), random.randint(0, height))
        # 画线条,开始 结束点  线条颜色  线条宽度
        draw.line([begin, end], fill=cls.__gene_random_color(), width=2)

    @classmethod
    def __gene_points(cls, draw, point_chance, width, height):
        # 大小限制
        chance = min(50, max(0, int(point_chance)))
        for w in range(width):
            for h in range(height):
                tmp = random.randint(0, 100)
                if tmp > 100 - chance:
                    draw.point((w, h), fill=cls.__gene_random_color())

    # 生成随机的颜色
    @classmethod
    # 起始颜色 最终颜色
    def __gene_random_color(cls, start=0, end=255):
        # 初始化随机数
        random.seed()
        # 按范围生成随机输R  G  B
        return (random.randint(start, end), random.randint(start, end), random.randint(start, end))

    # 随机选择一个字体
    @classmethod
    def __gene_random_font(cls):
        fonts = [
            'STCAIYUN.TTF',
            'STFANGSO.TTF',
            'STLITI.TTF',
            'framd.ttf'
        ]
        # 随机选一个 字体
        font = random.choice(fonts)
        return font

    # 用来随机生成一个字符串(包括英文和数字)
    @classmethod
    def gene_text(cls, number):
        # cls.SOURCE生成list A-Z a-z 0-9  number是生成验证码的位数
        return ''.join(random.sample(cls.SOURCE, number))

    # 生成验证码
    @classmethod
    def gene_graph_captcha(cls):
        # 验证码图片的宽和高
        width, height = cls.size
        # 创建图片
        # R:Red(红色)0-255  G:G(绿色)0-255   B:B(蓝色)0-255    A:Alpha(透明度),添加了A,则就只能生成png图片
        image = Image.new('RGB', (width, height), cls.__gene_random_color(0, 100))
        # 验证码的字体  随机产生字体 字体大小
        font = ImageFont.truetype(cls.__gene_random_font(), cls.fontsize)
        # 创建画笔
        draw = ImageDraw.Draw(image)
        # 随机生成4为字符串
        text = cls.gene_text(cls.number)
        # 获取字体的尺寸
        font_width, font_height = font.getsize(text)
        # 填充字符串 x y坐标 文本 字体 字体颜色
        draw.text(((width - font_width) / 2, (height - font_height) / 2),
                  text, font=font, fill=cls.__gene_random_color(150, 255))
        # 绘制干扰线 绘制多少条干扰线

        for x in range(0, cls.line_number):
            cls.__gene_line(draw, width, height)
            # 绘制噪点
            cls.__gene_points(draw, 10, width, height)
        return text, image


下面是我验证码对应的视图函数

from Code import Captcha
import base64   # Base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。
# 开启图片验证码
@csrf.exempt
@app.route("/Captcha", methods=["GET", "POST"])
def auth_code():
    # 获取验证码图片,和验证码值
    code, img = Captcha.gene_graph_captcha()
    buf = BytesIO()  # 构建一个输入输出流
    img.save(buf, "jpeg")     # 将图片保存到输入输出流,也就是内存中
    bur_str = buf.getvalue()    # 获得输入输出流里面的内容
    # session["Code"] = code   # 将验证码值存储到session中
    print(str(base64.b64encode(bur_str)))
    data = str(base64.b64encode(bur_str))[1:].strip("'")
    return data

视图函数中我们需要把二进制数据进行编码,这里python2和python3可以有点区别,或者是我生成的图片二进制数据有和别的有点区别,我打印出来的 base64.b64encode(bur_str)  是由 b' ' 所包括的,就如下图所示

这样就导致我的img标签src链接是这样的一种情况-----> src="data:image/jpg;base64,b'/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGzBQgHBwcJCQgKDBQNDAsLDBk ......' "

这样的话就导致网页上显示不了图片,但是去掉了 b' ' 就能正常显示图片了,所以我在视图函数中将其转换为字符串,然后切片去掉两边的单引号,最后再返回到HTML中去,

下面是我HTML中对应的img标签代码,以及Ajax代码

<!--验证码显示区域,点击验证码进行更新-->
 <tr>
     <td><a href="#"><img id="img" src= "data:image/jpg;base64,{{ img }}" ></a></td>
 </tr>
$("#img").click(function () {
    $.ajax({
        url: "/Captcha",
        type: "POST",
        data: {},
        dataType:"text",
        success: function (data) {
            $("#img").attr("src","data:image/jpg;base64,"+data)
        }, error: function () {
            alert("没有获取返回数据");
        }
    });
    // $.post(
    //    "/Captcha",{},function (data) {
    //         $("#img").attr("src","data:image/jpg;base64,"+data)
    //     }
    // )
});

使用jQuery中的$.post()方法也可以实现,代码很简单,js中点击图片则就会触发Ajax,然后post请求,获取数据,使用jQuery的attr()方法替换对应img标签的src属性,这样图片就可以显示在页面中了,

这里需要注意的是,如果你Ajax获取的数据不是乱码而是正常的数据,但是就是不显示图片,你就得去看看img标签src属性是否是正确,像我就出现了上面 那样的,图片数据被 b' '

包括  然后再被双引号包括,这样就导致了显示不了图片

猜你喜欢

转载自blog.csdn.net/rongDang/article/details/81225879