在服务端通过Javascript/PHP将带Logo的二维码保存为PNG/JPEG
问题:生成内嵌Logo的PNG/JPEG二维码无法正常打开
开发小型项目时需要生成带内嵌Logo的二维码,并保存为PNG或JPEG格式。当前代码在使用SVG格式时运行正常,但改为PNG/JPEG格式后,文件虽能保存却无法打开,系统提示格式不支持。
原前端HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>QR Code Styling</title> <script type="text/javascript" src="https://unpkg.com/qr-code-styling@1.5.0/lib/qr-code-styling.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <div id="canvas"></div> <script type="text/javascript"> const qrCode = new QRCodeStyling({ width: 300, height: 300, type: "svg", data: "https://www.facebook.com/", image: "https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg", dotsOptions: { color: "#4267b2", type: "rounded" }, backgroundOptions: { color: "#e9ebee", }, imageOptions: { crossOrigin: "anonymous", margin: 20 } }); var svgBlob = qrCode.getRawData('jpeg'); svgBlob.then(value => value.text().then(value => sendAjax(value))); function sendAjax(svgString) { $.ajax('saveqr.php', { 'data': svgString, //canvas.innerHTML, 'type': 'POST', 'processData': false, 'contentType': 'image/jpg' }); } qrCode.append(document.getElementById("canvas")); // qrCode.download({ name: "qr", extension: "svg" }); </script> </body> </html>
原后端saveqr.php代码
<?php $svg = file_get_contents('php://input'); $myfile = fopen("testfile.jpeg", "w"); fwrite($myfile, $svg); ?>
问题根源
- 生成位图二维码时,QRCodeStyling的
type参数仍设为svg,无法生成正确的二进制位图数据 - 读取Blob时错误使用
text()方法,将二进制图像数据转成字符串导致数据损坏 - PHP写入文件时使用文本模式,破坏了二进制图像的结构
修复后的代码
前端HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>QR Code Styling</title> <script type="text/javascript" src="https://unpkg.com/qr-code-styling@1.5.0/lib/qr-code-styling.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <div id="canvas"></div> <script type="text/javascript"> const qrCode = new QRCodeStyling({ width: 300, height: 300, type: "canvas", // 改为canvas类型以生成位图格式 data: "https://www.facebook.com/", image: "https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg", dotsOptions: { color: "#4267b2", type: "rounded" }, backgroundOptions: { color: "#e9ebee", }, imageOptions: { crossOrigin: "anonymous", margin: 20 } }); // 直接获取Blob并发送二进制数据,避免转文本损坏 qrCode.getRawData('jpeg').then(blob => { sendAjax(blob); }); function sendAjax(blob) { $.ajax('saveqr.php', { data: blob, type: 'POST', processData: false, contentType: 'image/jpeg' // 修正contentType为标准的image/jpeg }); } qrCode.append(document.getElementById("canvas")); </script> </body> </html>
后端saveqr.php代码
<?php // 读取二进制输入数据 $imageData = file_get_contents('php://input'); // 以二进制写入模式打开文件,避免损坏图像数据 $myfile = fopen("testfile.jpeg", "wb"); fwrite($myfile, $imageData); fclose($myfile); // 关闭文件句柄,确保数据写入完成 ?>
关键修改说明
- QRCodeStyling类型切换:将
type从svg改为canvas,让库基于Canvas生成位图,才能输出PNG/JPEG格式的二进制数据。 - Blob处理优化:直接传递Blob对象给AJAX,跳过文本转换步骤,保证二进制数据完整性。
- PHP写入模式修正:使用
wb二进制写入模式,避免文本模式下的编码转换破坏图像结构。
内容的提问来源于stack exchange,提问作者Nitin
相关产品推荐
相关产品推荐

