You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击按钮更新href下载文件时出现无限下载循环的问题排查

解决按钮触发文件下载时的无限循环问题

尝试实现点击按钮下载文件,步骤如下:

  • 点击按钮调用API获取文件Buffer Data
  • 将Buffer转换为base64 URL,更新<a>元素的href属性
  • 函数内部触发<a>元素的点击事件

该方法能成功下载文件,但会出现无限下载的情况。


原代码

调用方式

<button v-on:click="this.getImage([imageID, imageName], $event)"><a>View scoresheet</a></button>

函数代码

getImage: async function(info, event){
    fetch('endpoint' + String(info[0]) + "/" + String(info[1]) , {
        method: 'GET',
      
        })
        .then(response => response.json())
        .then(async result => {
             var image_data = await result.image_buffer.data
             var imgSrc = "data:image/jpg;base64," + btoa(
                 image_data.reduce((data, byte) => data + String.fromCharCode(byte), '')
             );

             event.target.href = imgSrc
             event.target.download = 'image.jpg'
             event.target.click()
        })
    },

问题原因

  1. DOM结构不符合规范:按钮内部嵌套<a>标签违反HTML语义,会导致事件冒泡干扰。
  2. 事件循环触发:当调用event.target.click()时:
    • 若event.target是按钮元素,点击会再次触发绑定的getImage方法,形成无限循环;
    • 若event.target是内部的<a>元素,其点击事件会冒泡到父级按钮,再次触发getImage,导致无限下载。

解决办法

方案1:使用隐藏的独立<a>元素(推荐)

修改DOM结构,将用于下载的<a>元素单独隐藏,避免事件冒泡干扰:

<button v-on:click="getImage([imageID, imageName])">View scoresheet</button>
<!-- 隐藏的下载专用a标签 -->
<a ref="downloadLink" style="display: none;"></a>

修改函数代码,通过Vue的ref获取隐藏元素触发下载:

getImage: async function(info){
    try {
        const response = await fetch(`endpoint${info[0]}/${info[1]}`, { method: 'GET' });
        const result = await response.json();
        const image_data = result.image_buffer.data;
        const imgSrc = "data:image/jpg;base64," + btoa(
            image_data.reduce((data, byte) => data + String.fromCharCode(byte), '')
        );

        const downloadLink = this.$refs.downloadLink;
        downloadLink.href = imgSrc;
        downloadLink.download = 'image.jpg';
        downloadLink.click();
    } catch (error) {
        console.error('下载失败:', error);
    }
},

方案2:临时阻止事件冒泡

若不想调整DOM结构,可在触发<a>点击时阻止事件冒泡,避免触发按钮的点击事件:

getImage: async function(info, event){
    fetch('endpoint' + String(info[0]) + "/" + String(info[1]) , {
        method: 'GET',
      
        })
        .then(response => response.json())
        .then(async result => {
             var image_data = await result.image_buffer.data
             var imgSrc = "data:image/jpg;base64," + btoa(
                 image_data.reduce((data, byte) => data + String.fromCharCode(byte), '')
             );

             // 精准获取内部的a元素
             const aElement = event.currentTarget.querySelector('a');
             aElement.href = imgSrc;
             aElement.download = 'image.jpg';
             // 单次阻止事件冒泡
             aElement.addEventListener('click', function(e) {
                 e.stopPropagation();
             }, { once: true });
             aElement.click();
        })
    },

内容的提问来源于stack exchange,提问作者doozy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 03:02:44