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

Firefox下粘贴剪贴板内容后input files数组读取异常问题

问题描述

我制作了一个最多支持上传5个文件的表单,初始仅显示一个<input type="file">,用户选择文件后会动态添加新的input,使用文件选择器时功能正常。添加剪贴板粘贴(CTRL+V)图片功能后,Firefox中出现异常:第二次粘贴时,$('.form-post-file-input')返回的第0个元素的.files数组为空,第1个元素包含剪贴板内容;虽然提交表单时第0个文件能正常上传,但读取.files却为空。该问题仅在Firefox中出现,Chromium内核的Brave浏览器无此问题。

复现代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <title>Document</title>
</head>
<body>
    <form class="form-post" role="form" method="POST" enctype="multipart/form-data" action="/someroute">
        <!-- other inputs... -->
        <div id="form-post-file-input-div">
            <div class="form-post-file-input-box">
                <input class="novo-post-form-item form-post-file-input" name="arquivos[]" type="file" onchange="addNovoInputFile(this, 5)">
            </div>    
        </div>
        </form>
        
        <script>
var addNovoInputFile = function(elem, max){
    fileInputs = $('.form-post-file-input');

    // When this loop is reached from a copypaste event, the content of fileInputs[0].files is empty
    // this doesn't happen when I just select a file from filepicker 
    for(var i=0; i < fileInputs.length; i++)
    {
        if(fileInputs[i].files.length === 0)
            return;
    }
    // I put this loop so I don't update the form in case, for example, if the user keeps updating a file at the 0th <input>
    // but maybe my solution is just changing the logic of this loop
    
    if(fileInputs.length >= max || elem.files.length === 0)
        return;
    
    var novoInput = "<div class=\"form-post-file-input-box\">";
    novoInput += "<input class=\"novo-post-form-item form-post-file-input\" name=\"arquivos[]\" type=\"file\" onchange=\"addNovoInputFile(this, " + max + ")\">";
    novoInput += "</div>"
    
    $(novoInput).appendTo(".form-post #form-post-file-input-div");
};

// New event I just added in order to fill the input with a printscreen content in the clipboard
window.addEventListener('paste', e => {
    let inputs = document.getElementsByName('arquivos[]');
    let inputToChange = inputs[inputs.length-1];

    if(e.clipboardData.files.length > 0){
        inputToChange.files = e.clipboardData.files;
        addNovoInputFile(inputToChange, 5);
    }
});


        </script>
</body>
</html>

解决方案

问题根源

Firefox对直接赋值input.files设置文件的处理逻辑和Chromium存在差异:

  1. 直接赋值不会触发input的change事件,导致原有状态判断逻辑失效
  2. 后续读取旧input的files属性时,Firefox的安全机制会返回空数组,但实际表单提交时文件数据是保留的

修改方案

调整addNovoInputFile的判断逻辑,改用自定义标记统计已填充文件的input数量,同时优化粘贴事件的文件设置方式:

var addNovoInputFile = function(elem, max){
    const fileInputs = $('.form-post-file-input');
    // 统计已包含文件的input数量,兼容Firefox下粘贴文件的情况
    let filledCount = 0;
    fileInputs.each(function() {
        if(this.files.length > 0 || this.dataset.hasFile === 'true'){
            filledCount++;
        }
    });

    // 已达上限或当前input无文件时,不添加新input
    if(filledCount >= max || (elem.files.length === 0 && elem.dataset.hasFile !== 'true')){
        return;
    }
    
    var novoInput = "<div class=\"form-post-file-input-box\">";
    novoInput += "<input class=\"novo-post-form-item form-post-file-input\" name=\"arquivos[]\" type=\"file\" onchange=\"addNovoInputFile(this, " + max + ")\">";
    novoInput += "</div>"
    
    $(novoInput).appendTo(".form-post #form-post-file-input-div");
};

window.addEventListener('paste', e => {
    let inputs = document.getElementsByName('arquivos[]');
    let inputToChange = inputs[inputs.length-1];

    if(e.clipboardData.files.length > 0){
        // 使用DataTransfer设置文件,同时标记该input已填充
        const dt = new DataTransfer();
        dt.items.add(e.clipboardData.files[0]);
        inputToChange.files = dt.files;
        inputToChange.dataset.hasFile = 'true';
        addNovoInputFile(inputToChange, 5);
    }
});

关键修改点

  1. 新增dataset.hasFile自定义属性,标记通过粘贴填充的input,解决Firefox下files读取为空的判断问题
  2. 替换原有循环检查逻辑,通过统计filledCount判断已填充文件的input数量
  3. 使用DataTransfer对象设置粘贴文件,让Firefox能正确识别文件状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 04:47:25