PHP生成二维码
最近做页面保存长图的功能,长图底部需要附带页面地址二维码,之前没搞过二维码相关的实现,在Google上搜索一番,发现了两个现有的轮子phpqrcode扩展和qr-code扩展。
对比发现phpqrcode很多年没有维护了,最终选择了qr-code。
注:如果使用phpqrcode可以参考PHP基于phpqrcode类生成二维码
使用qr-code生成二维码很容易,参考这篇文章PHP生成二维码。
需要注意三点:
0、生成二维码的create方法中,默认添加header,直接显示在浏览器,如果需要接受二进制的二维码信息,需要去掉header
/** * 生成二维码 * @param $content 需要写入的内容 * @return array | page input */ public function create($content) { $this->_qr = new QrCode($content); $this->_qr->setSize($this->_size); $this->_qr->setWriterByName(self::WRITE_NAME); $this->_qr->setMargin(self::MARGIN); $this->_qr->setEncoding($this->_encoding); $this->_qr->setErrorCorrectionLevel(ErrorCorrectionLevel::HIGH); $this->_qr->setForegroundColor(self::FOREGROUND_COLOR); $this->_qr->setBackgroundColor(self::BACKGROUND_COLOR); if ($this->_title) { $this->_qr->setLabel($this->_title_content, 16, '字体地址', LabelAlignment::CENTER); } if ($this->_logo) { $this->_qr->setLogoPath($this->_logo_url); $this->_qr->setLogoWidth($this->_logo_size); $this->_qr->setRoundBlockSize(true); } $this->_qr->setValidateResult(false); if ($this->_generate == 'display') { // 前端调用 例:<img src="http://localhost/qr.php?url=base64_url_string"> header('Content-Type: ' . $this->_qr->getContentType()); return $this->_qr->writeString(); } else if ($this->_generate == 'writefile') { return $this->_qr->writeString(); } else { return ['success' => false, 'message' => 'the generate type not found', 'data' => '']; } }
1、PHP生成base64编码图片的时候,注意带上前缀字符串
$qr_img = $qr_code->create($qr_url); $base64_img = "data:image/png;base64," . base64_encode($qr_img); function base64_encode_image ($filename=string,$filetype=string) { if ($filename) { $imgbinary = fread(fopen($filename, "r"), filesize($filename)); return 'data:image/' . $filetype . ';base64,' . base64_encode($imgbinary); } }
2、使用PHP解码base64格式图片的时候,也需要先去掉前缀
// 截取data:image/png;base64, 这个逗号后的字符 $base64_string= explode(',', $base64_string); $data= base64_decode($base64_string[1]);
二维码传到页面的坑
0、计划方案是:页面加载的时候把生成的二维码转成base64格式,存人MC, 然后放在页面的隐藏域上,前端获取隐藏域的内容然后绘图。
1、坑:Chrome报错 net::ERR_INCOMPLETE_CHUNKED_ENCODING
查了下大概的原因是从服务端返回的数据不完整,被截断了。尝试了各种解决方案无果。
2、解决:后来通过ajax单独请求接口获取base64二维码。【渲染页面单传二维码是可以的,如果同时附带了其他变量就报错,具体原因还需进一步排查】
3、思考:事后看来这种方案有些欠考虑,在做之前看到很多人说后端生成二维码坑比较多,很耗CPU资源,对服务器的压力比较大,建议前端生成。当时查了JS生成二维码的库qrcodejs不支持加logo,就放弃了。性能慢的问题还没遇到,倒是先遇到了传输的问题。
图片为啥要用base64编码后的格式传输
关于base64编码原理和应用这里不做讨论
我理解的原因
0、图片二进制信息不兼容。
某些二进制值,在一些硬件上,比如在不同的路由器、老电脑上,表示的意义不一样,做的处理也不一样。同样,一些老的软件,网络协议也有类似的问题。
1、前端在实现页面时,对于一些简单图片,通常会选择将图片内容直接内嵌在页面中,避免不必要的外部资源加载,增大页面加载时间,但是图片数据是二进制数据,转为base64就可以直接显示。的src属性可以直接潜入base64格式图片,CSS的属性也支持直接潜入base64格式图片。
2、更进一步的解说可参考知乎这个问题, 为什么要使用base64编码,有哪些情景需求?
另外:图片转Base64,这个在线工具超级好用
参考:
PHP手册base64_encode
维基百科Base64Base64编码原理和应用