PHP生成二维码传到页面的坑

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编码原理和应用

发表评论

电子邮件地址不会被公开。 必填项已用*标注