首页 > 解决方案 > javascript+browser 复制到剪贴板失败,数据超过 ~150k 使用 document.execCommand('copy')

问题描述

使用 document.execCommand('copy') 复制到剪贴板(a la https://stackoverflow.com/a/30810322/3160967)适用于少量数据,如果您使用调试器单步执行,也适用,但失败当数据大小达到大约 150k 时(并且您没有使用调试器单步执行)。

此外,如果以 window.getSelection() 开头的代码异步运行,它似乎可以工作。为什么?异步解决方案是稳定的,还是只是掩盖而不解决问题?

使用 Chrome 版本 66.0.3359.139

要重现此问题,请打开 DevTools 并运行以下命令:

function doclick() { 
  copyTest(); 
}

document.addEventListener('click', doclick);

function copyTest() {
    var data = [];
    var n = 20000; // works if n is smaller e.g. < ~6000

    for(var i = 0; i < n; i++)
      data[i] = String(Math.random());

    var textarea = document.createElement('textarea');
    textarea.value = data.join('\t')

    document.body.appendChild(textarea);

    var sel = window.getSelection(); // works if debugger breaks here or earlier
    sel.removeAllRanges();

    var r = document.createRange();
    r.selectNode(textarea);
    sel.addRange(r);

    document.execCommand('copy');
    document.body.removeChild(textarea);
    alert('copied ' + textarea.value.length);
}

在 DevTools 中运行它后,我点击页面运行 doCopy(),但剪贴板没有改变。但是,如果 n < 6000 左右,它会成功。此外,如果我在上面指示的行上设置一个断点,然后在它中断后继续运行代码,它将起作用。

此外,以下似乎有效:

function copyTest() {
    var data = [];
    var n = 20000; // works only if n is smaller e.g. < ~6000

    for(var i = 0; i < n; i++)
      data[i] = String(Math.random());

    var textarea = document.createElement('textarea');
    textarea.value = data.join('\t')

    document.body.appendChild(textarea);

    function copy() {
        var sel = window.getSelection(); // works if debugger breaks here or earlier
        sel.removeAllRanges();

        var r = document.createRange();
        r.selectNode(textarea);
        sel.addRange(r);

        document.execCommand('copy');
        document.body.removeChild(textarea);
        alert('copied ' + textarea.value.length);
    }
    window.setTimeout(copy); // this works
}

但是,我不确定为什么这应该起作用。看起来当window.getSelection在document.body.appendChild之后立即被调用时,当被追加的孩子有足够的数据量时,window.getSelection失败,可能是因为document.body.appendChild需要另一个异步循环才能完成?无论如何,这个问题的“正确”解决方案是什么——在纯 JS 中?

标签: javascriptgoogle-chromeclipboard

解决方案


推荐阅读