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

如何在单页实现多个自定义文件上传组件并解决选中文件不显示问题

多文件上传组件修复方案

核心问题说明

  • 页面内所有上传组件重复使用了相同的id my-file,label的for属性绑定同一个id,导致label与输入框关联异常
  • 给label绑定的click事件添加了return false,阻止了label默认触发关联输入框选择文件的行为
  • JS中the_return是所有.file-return元素的节点集合,无法直接对整体设置innerHTML,需要定位到当前触发事件的输入框对应的展示元素
  • 未添加拖拽相关事件监听,拖拽上传功能无法生效
  • 直接取input.value会显示浏览器默认的伪路径,展示效果差,建议直接取文件名

修复后代码

HTML代码

<div class="upload--input__custom">
     <div class="upload--container"> 
          <p>Drop files here or</p> 
          <input class="upload--input" id="my-file1" type="file">
          <label tabindex="0" for="my-file1" class="upload--label">Select Files</label>
          <p class="file-return"></p>
     </div>
</div>

<div class="upload--input__custom">
     <div class="upload--container"> 
          <p>Drop files here or</p> 
          <input class="upload--input" id="my-file2" type="file">
          <label tabindex="0" for="my-file2" class="upload--label">Select Files</label>
          <p class="file-return"></p>
     </div>
</div>

JS代码

var fileInput = document.querySelectorAll(".upload--input"),  
    button = document.querySelectorAll(".upload--label"),
    containers = document.querySelectorAll(".upload--container");
            
for (let i = 0; i < button.length; i++) {
     button[i].addEventListener("keydown", function(event) {  
       if (event.keyCode == 13 || event.keyCode == 32) {  
           this.previousElementSibling.click();
       }  
     }); 
}

// 移除阻止默认行为的return false,保留聚焦逻辑即可
for (let i = 0; i < button.length; i++) {
    button[i].addEventListener("click", function(event) {
      this.previousElementSibling.focus();
    });             
}

for (let i = 0; i < fileInput.length; i++) {
     fileInput[i].addEventListener("change", function(event) {
       // 找到当前输入框对应的file-return元素
       const currentReturn = this.parentElement.querySelector('.file-return');
       // 优先取文件名展示
       currentReturn.innerHTML = this.files.length ? this.files[0].name : this.value;  
     });            
}

// 添加拖拽功能
for (let i = 0; i < containers.length; i++) {
  // 阻止拖拽默认行为
  containers[i].addEventListener('dragenter', (e) => e.preventDefault());
  containers[i].addEventListener('dragover', (e) => e.preventDefault());
  containers[i].addEventListener('drop', function(e) {
    e.preventDefault();
    const currentInput = this.querySelector('.upload--input');
    const currentReturn = this.querySelector('.file-return');
    // 赋值拖拽的文件到输入框
    currentInput.files = e.dataTransfer.files;
    // 展示文件名
    currentReturn.innerHTML = currentInput.files.length ? currentInput.files[0].name : '';
  })
}

CSS代码

CSS部分无需修改,可直接沿用原有代码:

.upload--input__custom{
    border: 1px dashed black;
    height: 200px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    border-radius: 10px;
    -webkit-border-radius: 10px;
    -moz-border-radius: 10px;
    -ms-border-radius: 10px;
    -o-border-radius: 10px;
}

.upload--container {
    position: relative;
    width: 100%;
    margin: 0 auto;
    text-align: center;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
}

.upload--container p{
    color: blue;
    margin-bottom: .75rem;
    font-size: 17px;
}

.upload--label {
    width: fit-content !important;
    display: block;
    padding: 12px 20px;
    background: yellow;
    color: #fff !important;
    font-size: 1em;
    transition: all 0.4s;
    cursor: pointer;
    -webkit-transition: all 0.4s;
    -moz-transition: all 0.4s;
    -ms-transition: all 0.4s;
    -o-transition: all 0.4s;
}

.upload--label::after{
    content: unset !important;
}

.upload--input {
    opacity:0;
    width: 100% !important;
    height: 100%;
    padding: 14px 0;
    cursor: pointer;
    width: fit-content;
    position: absolute;
    left:0;
    top: 0;
    z-index: 1000;
}
  
.file-return {
    margin: 0;
    width: 70%;
    height: 30px;
    background-color: burlywood;
}
.file-return:not(:empty) {
    margin: 1em 0;
    text-align: center;
}
.file-return {
    font-style: italic;
    font-size: 0.9em;
    font-weight: bold;
}

.file-return:not(:empty):before {
    content: "Selected file: ";
    font-style: normal;
    font-weight: normal;
}

内容的提问来源于stack exchange,提问作者h.m.p.frontendDeveloper

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 06:27:04