javascript+browser copy to clipboard fails with data exceeding ~150k using document.execCommand('copy')

隐身守侯 提交于 2019-12-11 03:21:07

问题


Copy to clipboard using document.execCommand('copy') (a la https://stackoverflow.com/a/30810322/3160967) works fine with small amounts of data, and also works if you step through with a debugger, but fails when data size hits about 150k (and you don't step through with a debugger).

Furthermore, it seems to work if the code starting with window.getSelection() is run asynchronously. Why? And is the async solution stable, or is it just masking but not solving the problem?

Using Chrome version 66.0.3359.139

To reproduce this problem, open DevTools and run the following:

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);
}

After I run this in DevTools, I click on the page to run doCopy(), but the clipboard is unchanged. However, if n < 6000 or so, it will succeed. In addition, it will work if I set a breakpoint on the indicated line above and then continue to run the code after it breaks.

Furthermore, the below seems to work:

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
}

However, I'm not sure why this should work. It appears that when window.getSelection is called immediately after document.body.appendChild, when the child being appended has a sufficient amount of data, window.getSelection fails, perhaps because document.body.appendChild needs another async cycle to complete? In any case, what is a "proper" solution to this issue-- in pure JS?

来源:https://stackoverflow.com/questions/50413745/javascriptbrowser-copy-to-clipboard-fails-with-data-exceeding-150k-using-docum

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!