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

如何修改Chrome扩展实现文件上传前自定义确认弹窗?

问题描述

我正在开发一款Chrome扩展,需要在用户尝试上传文件时弹出自定义模态窗口请求确认。以下是我编写的content.js脚本:

function showModal(element) {
  const modal = document.createElement('div');

  modal.innerHTML = `
    <div style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);display:flex;justify-content:center;align-items:center;z-index:10000;">
      <div style="background:white;padding:20px;border-radius:5px;box-shadow:0 4px 6px rgba(0,0,0,0.1);">
        <p>Are you sure you want to upload the file?</p>
        <button id="confirmUpload">Yes</button>
        <button id="cancelUpload">No</button>
      </div>
    </div>
  `;

  document.body.appendChild(modal);

  // 处理确认上传
  document.getElementById('confirmUpload').addEventListener('click', () => {
    document.body.removeChild(modal);
  });

  // 处理取消上传
  document.getElementById('cancelUpload').addEventListener('click', () => {
    document.body.removeChild(modal);
    // 清空input的文件
    const dt = new DataTransfer()
    element.files = dt.files;
  });
}

// 监听用户上传文件的事件
document.addEventListener('change', (event) => {
    event.preventDefault();
    const element = event.target;
    
    if (element instanceof HTMLInputElement && element.type === 'file') {
        showModal(element);
    }
}, true);

核心问题

文件会在用户选择后立即开始上传,用户还未响应弹窗就已经触发上传流程,完全违背了确认上传的初衷。

常规方案不可行的原因

  • 使用event.stopPropagation()不可行:需要针对每个网站编写自定义上传逻辑,不具备通用性。
  • 标准alert/prompt/confirm对话框不适用:无法自定义样式和添加文件预览等扩展功能。
解决方案

核心思路是在文件选择对话框弹出前拦截操作,而非等用户选完文件触发change事件后再处理——很多网站会监听change事件并立即发起上传,此时拦截已经滞后。

方法1:劫持File Input的点击行为(通用方案)

直接拦截所有file input的点击事件,先弹出自定义确认框,用户确认后再触发原生文件选择流程,确保上传逻辑完全受控制。

修改后的content.js代码:

function showConfirmModal(onConfirm, onCancel) {
  const modal = document.createElement('div');
  modal.innerHTML = `
    <div style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);display:flex;justify-content:center;align-items:center;z-index:10000;">
      <div style="background:white;padding:20px;border-radius:5px;box-shadow:0 4px 6px rgba(0,0,0,0.1);">
        <p>确定要选择文件上传吗?</p>
        <button id="confirmBtn">确定</button>
        <button id="cancelBtn">取消</button>
      </div>
    </div>
  `;
  document.body.appendChild(modal);

  document.getElementById('confirmBtn').addEventListener('click', () => {
    document.body.removeChild(modal);
    onConfirm();
  });

  document.getElementById('cancelBtn').addEventListener('click', () => {
    document.body.removeChild(modal);
    onCancel();
  });
}

// 拦截所有file input的点击事件,优先执行确认逻辑
document.addEventListener('click', (event) => {
  const target = event.target;
  if (target instanceof HTMLInputElement && target.type === 'file') {
    event.preventDefault();
    event.stopPropagation();
    
    showConfirmModal(
      // 用户确认后,触发原生文件选择
      () => {
        // 创建临时input避免干扰原元素的事件监听
        const tempInput = document.createElement('input');
        tempInput.type = 'file';
        tempInput.multiple = target.multiple;
        tempInput.accept = target.accept;
        
        // 临时input选完文件后,转移到原input并触发change事件
        tempInput.addEventListener('change', () => {
          target.files = tempInput.files;
          target.dispatchEvent(new Event('change', { bubbles: true }));
          tempInput.remove();
        });
        
        tempInput.click();
      },
      // 用户取消,无操作
      () => {}
    );
  }
}, true);

方法2:拦截表单提交(针对表单上传场景)

如果网站通过表单提交完成上传,可以拦截表单submit事件,检查是否有已选择的文件,再弹确认框:

document.addEventListener('submit', (event) => {
  const form = event.target;
  const fileInputs = form.querySelectorAll('input[type="file"]');
  
  // 检查表单内是否有已选择文件的input
  const hasSelectedFile = Array.from(fileInputs).some(input => input.files.length > 0);
  
  if (hasSelectedFile) {
    event.preventDefault();
    event.stopPropagation();
    
    showConfirmModal(
      () => form.submit(),
      () => {}
    );
  }
}, true);

补充说明

  • 方法1覆盖绝大多数场景:包括用户直接点击file input、网站通过JS触发file input点击的情况。
  • 若需添加文件预览功能,可在临时input的change事件中获取文件对象,先在确认弹窗内渲染预览,用户确认后再将文件转移到原input。
  • 事件监听需设置capture: true,确保拦截逻辑优先于网站自身的事件监听执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 16:52:31