使用goqr.me API生成二维码图片,带download属性的下载按钮无效,反而打开图片
问题根因
- 核心触发原因是违反了HTML
download属性的生效规则:该属性仅对同源资源、当前页面生成的blob/data URI类资源有效。你直接把download属性绑定到第三方跨域的二维码生成API资源上时,浏览器会出于安全策略完全忽略该属性的配置,按照默认逻辑处理资源——因为接口返回的是image/png类型内容,浏览器会直接打开图片预览,不会触发下载流程。 - 附带代码瑕疵:URL参数存在双重转义错误,将HTML中本该写的参数分隔符转义码
&错写为&,浏览器解析后会导致请求参数拼接异常,无法正常获取指定尺寸和内容的二维码。
可落地的解决方法
- 前端Canvas转Blob触发下载
该第三方二维码API默认支持CORS跨域请求,你可以直接在前端加载二维码图片到Canvas中,导出为当前页面生成的Blob对象,再把对象URL绑定到下载按钮上。因为Blob URL属于当前页面的同源资源,download属性会完全生效。
核心实现代码:const qrImage = document.querySelector('img.card-img-top'); const downloadLink = document.querySelector('a.btn-info'); // 跨域加载图片必须设置跨域属性,否则Canvas会被安全策略污染,无法导出内容 qrImage.crossOrigin = 'anonymous'; qrImage.onload = () => { const canvas = document.createElement('canvas'); canvas.width = qrImage.naturalWidth; canvas.height = qrImage.naturalHeight; canvas.getContext('2d').drawImage(qrImage, 0, 0); canvas.toBlob((blob) => { downloadLink.href = URL.createObjectURL(blob); }, 'image/png'); } - 服务端代理中转
在自有网站的服务端实现简单的转发接口,接收前端传入的二维码参数,向第三方二维码API请求图片二进制流,返回响应时设置Content-Disposition: attachment; filename="qrcode.png"响应头。这种方式下浏览器会识别到强制下载的响应规则,直接触发下载,不需要依赖前端的download属性。 - 修正URL转义错误
把代码中两处图片地址里的&替换为&,保证请求参数能被正确解析,正常获取对应配置的二维码图片。
内容的提问来源于stack exchange,提问作者Esquirish
相关产品推荐
相关产品推荐

