我用python的PIL生成了验证码图片,需要将图片返回给前端浏览器,有两种返回方式。一种是返回response,另一种是将图片进行base64编码后返回。

注意:PIL生成验证码图片时,需要传入font参数,是字体文件,从系统中复制出来的字体文件不能改名,而且它的路径最好写绝对路径,否则在服务器运行或者说命令行运行时,会找不到这个字体文件,导致无法生成验证码图片,去服务器日志查看有报错OSError: cannot open resource。若是在本地用pycharm运行,不写绝对路径也没有这个问题,详细原因看另一篇文章。

先放两种方法的服务端公共代码

def random_string(length=32): # 生成32位随机字符串,原本是为了生成随机文件名,用于保存上传的头像,所以默认32位import randomstring='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'return ''.join(random.choice(string) for i in range(length))def random_color():r=random.randint(0,255)g=random.randint(0,255)b=random.randint(0,255)if r*0.299+g*0.578+b*0.114>=100: # 它们的和越小,颜色越深。from https://blog.csdn.net/qq_36843675/article/details/79448051和https://blog.csdn.net/dKnightL/article/details/107222075return (r,g,b)else:return random_color() # 递归,直到满足条件才停止,避免产生深色画布def generate_verification_code_image(length=4):size=130,50image=Image.new('RGB',size=size,color=random_color()) # 创建画布,返回Image对象。https://pillow.readthedocs.io/en/stable/font=ImageFont.truetype(os.path.abspath(os.path.dirname(__file__))+'/times.ttf',size=40) # 创建字体,是系统中的Times New Roman 常规,从系统中复制出来就是这个文件名,不能修改文件名,否则前端加载不出验证码图片(服务端控制台报错OSError: cannot open resource),即访问者的系统中需有这个字体。不建议只写'times.ttf',虽然和代码文件在同一个目录,但服务器命令行找不到字体文件('./times.ttf'也不行),pycharm可以,所以为了跨平台,用绝对路径draw=ImageDraw.Draw(image) # 创建ImageDraw对象,相当于创建画笔,参数是画布str=random_string(length)for i,value in enumerate(str): # 绘制验证码draw.text((5+random.randint(4,7)+25*i,1+random.randint(2,8)+2*i),text=value,fill=random_color(),font=font) # 第一个参数是每个字符的左上角的坐标,横坐标里25是固定字符间距,前面是随机字符间距,实际字符间距等于它们的和;text是要绘制的字符,fill是字符颜色for j in range(random.randint(5,8)): # 绘制干扰直线# 将画布平均分成上下两部分,使每条线的第一个端点在上部分,第二个端点在下部分,干扰效果更好x1=random.randint(0,130)y1=random.randint(0,50/2)x2=random.randint(0,130)y2=random.randint(50/2,50)draw.line(((x1,y1),(x2,y2)),fill=random_color()) # 第一个参数是每条线的端点坐标,fill是线条颜色for k in range(random.randint(5,8)): # 绘制干扰弧线from https://blog.csdn.net/qq_34356800/article/details/86744042,将他的size[0]改成了130,size[1]改成了50start=(-50,-50) # 起始位置在外边看起来才会像弧线end=(130+10,random.randint(0,50+10))draw.arc(start+end,0,360,fill=random_color())for m in range(130): # 绘制干扰点for n in range(50):number=random.randint(1,100)if number>90: # 只有10%的概率画点,概率再大的话影响人识别draw.point((m,n),fill=random_color())'''for i in range(40): # 绘制干扰点和干扰线 from https://www.cnblogs.com/Zzbj/p/13797672.htmldraw.point([random.randint(0,130),random.randint(0,50)],fill=random_color())x=random.randint(0,130)y=random.randint(0,50)draw.arc((x,y,x+4,y+4),0,90,fill=random_color())'''image=image.filter(ImageFilter.SMOOTH) # 返回添加了过滤器的Image对象,SMOOTH让图片模糊# image.show() # 展示图片return str,image

一.返回response

服务端主要代码

@user.route('/verification_code_image')
def verification_code_image():verification_code,image=generate_verification_code_image(4)session['verification_code']=verification_code # 多人访问时,验证码会存在各自的session里,不会发生后访问的人的验证码覆盖前面的人的验证码。若放在redis缓存里,写cache.set('verification_code',verification_code,timeout=120)会发生前面说的覆盖的情况,因每次存入redis的键值对的键相同buffer=BytesIO()image.save(buffer,"PNG") # 将Image对象转为二进制存入buffer。因BytesIO()是在内存中操作,所以实际是存入内存buf_bytes=buffer.getvalue() # 从内存中取出bytes类型的图片response=make_response(buf_bytes)response.headers['Content-Type']='image/png' # 设置请求头,文件格式与前面save时一致return response

上面的代码是服务端验证验证码是否正确,也可以在前端验证,只需将验证码字符串的存放位置由session(或redis)改为cookie,前端验证时从cookie中取值(cookie是存在本地的),这样可以节省服务器和数据库资源开销。

response参考链接1,参考链接2,参考链接3,参考链接4

前端主要代码

<script>$(function (){ //使用jQuery时,JavaScript代码直接写在$()内$('#recaptcha').after('<img src=\"{{ url_for("user.verification_code_image") }}\" id=\"img\" alt=\"验证码图片加载失败\" />') //三层引号嵌套from https://blog.csdn.net/feiyangbaxia/article/details/49681131和https://blog.csdn.net/zhongyangjian/article/details/46010157$('#img').click(function (){$(this).attr('src',"{{ url_for('user.verification_code_image') }}?ran="+Math.random()) //带一个随机数,否则点击时请求的路由与点击前加载的一致,服务端会返回相同的结果,即点击前加载的结果})})
</script>

二.将图片进行base64编码后返回

由于验证码图片很小,所以base64编码后不太影响网页性能

服务端主要代码

@user.route('/verification_code_image')
def verification_code_image():verification_code,image=generate_verification_code_image(4)session['verification_code']=verification_code # 多人访问时,验证码会存在各自的session里,不会发生后访问的人的验证码覆盖前面的人的验证码。若放在redis缓存里,写cache.set('verification_code',verification_code,timeout=120)会发生前面说的覆盖的情况,因每次存入redis的键值对的键相同buffer=BytesIO()image.save(buffer,"PNG") # 将Image对象转为二进制存入buffer。因BytesIO()是在内存中操作,所以实际是存入内存buf_bytes=buffer.getvalue() # 从内存中取出bytes类型的图片base64_data=base64.b64encode(buf_bytes) # 将bytes类型按base64进行编码,返回值还是bytes类型with open('1.txt','wb') as file:file.write(b'data:image/png;base64,'+base64_data) # 将1.txt中的内容复制到浏览器地址栏,直接访问就显示图片base64_data2='data:image/png;base64,'+str(base64.b64encode(buf_bytes),'utf-8') # 1.txt中的内容和base64_data2一样,也可以用base64_data3的写法# base64_data3=(b'data:image/png;base64,'+base64_data).decode('utf-8')return render_template('index.html',result=base64_data2)

base64参考链接5,参考链接6,参考链接7

前端主要代码

<img src="{{result}}">

对于方式二,如果服务端像return response那样直接return base64_data2,前端也用方式一的代码,则浏览器无法加载验证码图片,因为此时浏览器的Elements里验证码标签的src是src="/user/verification_code_image",问题出在url_for()。而方式二的浏览器的Elements里验证码标签的src是src="很长的字符串",这个很长的字符串可以手动复制到浏览器地址栏访问,也能显示验证码图片,类似通过网址或本地路径加载图片。

python验证码,python将PIL生成的图片进行base64编码并返回给前端浏览器相关推荐

  1. Java中使用Base64进行编码解码的工具类-将验证码图片使用Base64编码并返回给前端

    场景 前端使用Vue,验证码图片的src属性来自于后台SpringBoot接口. 后台验证码接口生成验证码图片并将其使用Base64进行编码. 前端就可以直接使用 data:image/png;bas ...

  2. [转载] python程序所需的图片通过base64编码成字符串放在代码中

    参考链接: 在Python中编码和解码Base64字符串 问题背景 python代码打包成exe可执行文件.问题是这个python程序执行时需要显示一张图片,这就意味着打包成exe后,也需要在exe同 ...

  3. python自带的PIL库扩展图片大小给图片加上文字描述

    利用python自带的PIL库扩展图片大小给图片加上文字描述.大多都是库函数调用,只是给定图片宽度后计算文字所需行数的代码需要写. 代码比较丑,but it works. #!/usr/bin/env ...

  4. [转载] python将图片进行base64编码, 解码

    参考链接: 在Python中编码和解码Base64字符串 一.将图片进行base64编码 import base64 img_path = 'D:xxx/file/img/juwan.jpg' wit ...

  5. Python实现jpg/png/jpeg图片转base64编码文件

    python实现图片转base64编码文件 #Python实现jpg/png/jpeg图片转base64编码文件 # 打开图片文件(可以是jpg/png/JPEG格式)转为二进制文件 with ope ...

  6. python将图片导出数据库_python 将图片转换为base64编码转储进数据库

    # _*_ coding: utf-8 _*_ #中间件:拓展工具遍历文件夹,对文件夹图片进行base64编码,写入数据库,并且读取查找方法 __author__ = 'wf15038' __date ...

  7. 图片转换为base64编码后,实现无图片展示图片

    第一部分,将图片转换为base64编码输出为txt文本 第二部分,将转换出来的base64编码赋值给b64_code,通过base64编码转换为图片,打开,然后删除 base64编码过长,同时输入过多 ...

  8. Markdown 插入图片 基于base64编码

    流程 将图片保存在本地 将图片转码至base64编码 在文档中插入编码 markdown使用 ![toc][toc_base64][toc_base64]:https://img-blog.csdni ...

  9. PHP 图片转base64编码 和 base64编码字符串转换成图片保存

    1.图片转base64编码: /*图片转换为 base64格式编码*/ $img = 'uploads/01.png'; $base64_img = base64EncodeImage($img); ...

最新文章

  1. 排序算法三:插入排序
  2. [编程题]字符串最后一个单词的长度
  3. Spring Cloud依赖
  4. spring boot + vue + element-ui全栈开发入门
  5. C# Regex类详解
  6. Visual Studio 2017 15.6发布
  7. zt:缓存一致性(Cache Coherency)入门 cach coherency
  8. Failed to update system registry. Need permission to add?
  9. 哪些异常是RuntimeException?Sql异常属于RuntimeException吗?Spring下SQL异常事务回滚
  10. C++函数内部实现的规则
  11. 购物车的简单添加与计算
  12. 全能App研发助手!滴滴开源DoraemonKit
  13. 互联网扫描器 ZMap 完全手册
  14. MPlayer 音乐播放器项目讲解
  15. 小程序  跳转web-view  点击左上角返回需要点击2次才能返回
  16. jupyter 或者 zeppelin 的下一代工具 polynote
  17. 夕阳红旅游团第三周报告
  18. 六脚自锁开关引脚图及功能定义
  19. 少壮不努力,长大搞IT
  20. 一台液晶显示屏的台式计算机,台式电脑液晶显示器怎么购买?

热门文章

  1. NYOJ 354 问当n个物品合成一个时,最小重量是多少?
  2. CORBA组件编程方法实例+分析
  3. 笔记----关于js只比较日期不比较时间
  4. ssh重装ubuntu_ubuntu安装ssh,安装失败
  5. java中npe问题是什么_JAVA8如何妙用Optional解决NPE问题详解
  6. 开源啦!一款基于Vue3 + Vite + TS的简历制作神器~~
  7. 《NFL橄榄球》:克利夫兰布朗·橄榄1号位
  8. python中isin函数_pandas中的isin函数详解
  9. Android P包管理机制之PackageManager简介
  10. 点更改计算机名闪退,我用win10电脑在编辑文件夹如删除,重命名之类时他会黑一下然后闪退,正常吗,怎么解决?,word一保存就闪退...