基于ASP.Net Core MVC实现复选框联动动态Dropzone表单
问题
我正在开发ASP.NET Core MVC项目,现有如下复选框:
<div class="form-check form-check-inline"> <input class="form-check-input" type="checkbox" id="10" value="10"> <label class="form-check-label" for="10">10sec</label> </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="checkbox" id="15" value="15"> <label class="form-check-label" for="15">15sec</label> </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="checkbox" id="30" value="30"> <label class="form-check-label" for="30">30sec</label> </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="checkbox" id="45" value="45"> <label class="form-check-label" for="45">45sec</label> </div>
我希望根据勾选的复选框动态添加带有Dropzone上传组件的卡片,目前仅能实现单个Dropzone的逻辑,想知道如何为所有复选框实现独立的动态Dropzone组件,也希望用更优的动态实现方式。
之前的单例实现示例如下:
function myFunction() { var checkBox = document.getElementById("10"); var text = document.getElementById("10secs"); if (checkBox.checked == true) { text.style.display = "block"; } else { text.style.display = "none"; } } //dropzone script var myDropzone = new Dropzone("#mydropzone", { url: "/test/create", maxFilesize: 3.0, uploadMultiple: false, createImageThumbnails: false, addRemoveLinks: true, removedfile: function(file) { var name = file.name; file.previewElement.remove(); $.ajax({ type: 'POST', url: '/test/delete', data: "fileName=" + name, dataType: 'html' }); }, maxFiles: 1, maxfilesexceeded: function(file) { this.removeAllFiles(); this.addFile(file); }, init: function() { var drop = this; this.on('error', function(file, errorMessage) { if (errorMessage.indexOf('Error 404') !== -1) { var errorDisplay = document.querySelectorAll('[data-dz-errormessage]'); errorDisplay[errorDisplay.length - 1].innerHTML = 'Error 404: The upload page was not found on the server'; } if (errorMessage.indexOf('File is too big') !== -1) { alert('i remove current file'); drop.removeFile(file); } }); } });
<script src="https://unpkg.com/dropzone@5.9.3/dist/dropzone.js"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/basic.css" rel="stylesheet" /> <div class="form-check form-check-inline"> <input class="form-check-input" type="checkbox" id="10" value="10" onclick="myFunction()"> <label class="form-check-label" for="10">10sec</label> </div> <div class="row" id="10secs" style="display: none"> <div class="col-lg-12"> <div class="card"> <div class="card-header"> <h4 class="card-title">30sec</h4> </div> <div class="card-body"> <div> <div class="clsbox-1"> <div class="dropzone clsbox" id="mydropzone"> </div> </div> </div> </div> </div> </div> </div>
解决方案
核心思路
通过数据属性关联复选框与动态卡片,用通用逻辑处理所有复选框的勾选事件,动态生成唯一ID的Dropzone容器,同时维护已初始化的Dropzone实例集合,避免重复创建。
1. 重构HTML结构
给复选框添加统一类名,准备卡片挂载容器,去掉硬编码的静态卡片:
<script src="https://unpkg.com/dropzone@5.9.3/dist/dropzone.js"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/basic.css" rel="stylesheet" /> <!-- 复选框组 --> <div class="form-check-group"> <div class="form-check form-check-inline"> <input class="form-check-input duration-checkbox" type="checkbox" id="10" value="10"> <label class="form-check-label" for="10">10sec</label> </div> <div class="form-check form-check-inline"> <input class="form-check-input duration-checkbox" type="checkbox" id="15" value="15"> <label class="form-check-label" for="15">15sec</label> </div> <div class="form-check form-check-inline"> <input class="form-check-input duration-checkbox" type="checkbox" id="30" value="30"> <label class="form-check-label" for="30">30sec</label> </div> <div class="form-check form-check-inline"> <input class="form-check-input duration-checkbox" type="checkbox" id="45" value="45"> <label class="form-check-label" for="45">45sec</label> </div> </div> <!-- 动态卡片挂载容器 --> <div id="card-container" class="mt-3"></div>
2. 通用JavaScript逻辑
实现动态创建卡片、初始化独立Dropzone、管理实例的功能:
// 维护已创建的Dropzone实例,key为时长值 const dropzoneInstances = {}; // 监听所有复选框的勾选事件 document.querySelectorAll('.duration-checkbox').forEach(checkbox => { checkbox.addEventListener('change', handleCheckboxChange); }); function handleCheckboxChange(e) { const duration = e.target.value; const isChecked = e.target.checked; const cardId = `card-${duration}`; const dropzoneId = `dropzone-${duration}`; if (isChecked) { // 动态生成卡片HTML const cardHtml = ` <div class="row" id="${cardId}"> <div class="col-lg-12"> <div class="card"> <div class="card-header"> <h4 class="card-title">${duration}sec</h4> </div> <div class="card-body"> <div class="clsbox-1"> <div class="dropzone clsbox" id="${dropzoneId}"></div> </div> </div> </div> </div> </div> `; // 插入到容器中 document.getElementById('card-container').insertAdjacentHTML('beforeend', cardHtml); // 初始化Dropzone并保存实例 dropzoneInstances[duration] = new Dropzone(`#${dropzoneId}`, { url: `/test/create?duration=${duration}`, // 传递时长参数给后端 maxFilesize: 3.0, uploadMultiple: false, createImageThumbnails: false, addRemoveLinks: true, removedfile: function(file) { const name = file.name; file.previewElement.remove(); // 删除请求也携带时长参数 $.ajax({ type: 'POST', url: `/test/delete?duration=${duration}`, data: { fileName: name }, dataType: 'html' }); }, maxFiles: 1, maxfilesexceeded: function(file) { this.removeAllFiles(); this.addFile(file); }, init: function() { const drop = this; this.on('error', function(file, errorMessage) { if (errorMessage.includes('Error 404')) { const errorDisplay = document.querySelectorAll('[data-dz-errormessage]'); errorDisplay[errorDisplay.length - 1].textContent = 'Error 404: 服务器未找到上传页面'; } if (errorMessage.includes('File is too big')) { alert('文件过大,已移除当前文件'); drop.removeFile(file); } }); } }); } else { // 取消勾选时,销毁Dropzone实例并移除卡片 if (dropzoneInstances[duration]) { dropzoneInstances[duration].destroy(); delete dropzoneInstances[duration]; } const card = document.getElementById(cardId); if (card) card.remove(); } }
3. ASP.NET Core后端适配
修改控制器接口,接收duration参数来区分不同时长的上传目录:
public class TestController : Controller { // 上传接口 [HttpPost] public IActionResult Create(IFormFile file, int duration) { // 根据duration指定不同的存储路径 var uploadPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads", duration.ToString()); if (!Directory.Exists(uploadPath)) { Directory.CreateDirectory(uploadPath); } var filePath = Path.Combine(uploadPath, file.FileName); using (var stream = new FileStream(filePath, FileMode.Create)) { file.CopyTo(stream); } return Ok(); } // 删除接口 [HttpPost] public IActionResult Delete(string fileName, int duration) { var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads", duration.ToString(), fileName); if (System.IO.File.Exists(filePath)) { System.IO.File.Delete(filePath); } return Ok(); } }
优势说明
- 通用性:一套逻辑适配所有复选框,新增时长选项只需添加复选框,无需修改JS代码
- 独立性:每个Dropzone实例完全独立,上传/删除操作互不干扰
- 资源回收:取消勾选时销毁Dropzone实例并移除DOM,避免内存泄漏
- 后端区分:通过
duration参数实现不同时长的文件隔离存储
内容的提问来源于stack exchange,提问作者Jesus
相关产品推荐
相关产品推荐

