MVC 5 C#中基于DropZone JS按文档类型限制总文件大小
MVC5 C# 结合DropZoneJS实现按文档类型限制总大小的批量PDF上传方案
一、前端实现(DropZone配置与大小校验)
1. 页面HTML结构
先在视图中添加文档类型下拉框、DropZone容器和批量提交按钮:
<div class="form-group"> @Html.Label("文档类型", new { @class = "control-label" }) @Html.DropDownList("LKP_DocType", null, "请选择文档类型", new { @class = "form-control", id = "docTypeDropdown" }) </div> <div id="fileUploadZone" class="dropzone"></div> <button id="submitBtn" class="btn btn-primary mt-3" disabled>批量上传</button>
2. DropZone JS配置与自定义逻辑
核心是维护不同文档类型的总上传大小,监听文件添加/移除事件做校验,批量提交时携带文档类型参数:
// 按文档类型存储已选文件总大小 let totalSizeByDocType = { 1: 0, // Administrator 2: 0, // Manager 3: 0 // Programer }; const MAX_TOTAL_SIZE = 5 * 1024 * 1024; // 5MB转换为字节 // 初始化DropZone Dropzone.options.fileUploadZone = { url: '@Url.Action("Upload", "YourController")', // 替换为你的控制器上传方法路径 autoProcessQueue: false, // 关闭自动上传,手动触发批量提交 uploadMultiple: true, // 允许批量上传 parallelUploads: 100, // 并行上传数量 maxFilesize: 5, // 单文件最大5MB acceptedFiles: ".pdf", // 仅允许PDF文件 addRemoveLinks: true, // 显示移除文件链接 init: function() { const myDropzone = this; const submitBtn = document.getElementById("submitBtn"); const docTypeDropdown = document.getElementById("docTypeDropdown"); // 切换文档类型时清空当前队列,避免跨类型文件混淆 docTypeDropdown.addEventListener("change", () => { myDropzone.removeAllFiles(true); submitBtn.disabled = true; }); // 文件加入队列时校验并更新总大小 this.on("addedfile", function(file) { const selectedTypeId = parseInt(docTypeDropdown.value); if (!selectedTypeId) { myDropzone.removeFile(file); alert("请先选择文档类型"); return; } // 累加总大小 totalSizeByDocType[selectedTypeId] += file.size; // 校验总大小是否超限 if (totalSizeByDocType[selectedTypeId] > MAX_TOTAL_SIZE) { myDropzone.removeFile(file); totalSizeByDocType[selectedTypeId] -= file.size; alert(`当前文档类型总上传大小不能超过5MB,已超出限制`); return; } // 有文件时启用提交按钮 submitBtn.disabled = false; }); // 文件被移除时更新总大小 this.on("removedfile", function(file) { const selectedTypeId = parseInt(docTypeDropdown.value); if (selectedTypeId) { totalSizeByDocType[selectedTypeId] -= file.size; // 队列为空时禁用提交按钮 submitBtn.disabled = myDropzone.getQueuedFiles().length === 0; } }); // 点击提交按钮触发批量上传 submitBtn.addEventListener("click", () => { const selectedTypeId = parseInt(docTypeDropdown.value); if (!selectedTypeId) { alert("请先选择文档类型"); return; } // 给上传请求携带文档类型参数 myDropzone.options.params = { LKP_DocType: selectedTypeId }; myDropzone.processQueue(); }); // 上传完成后重置状态 this.on("queuecomplete", () => { myDropzone.removeAllFiles(true); submitBtn.disabled = true; const selectedTypeId = parseInt(docTypeDropdown.value); if (selectedTypeId) totalSizeByDocType[selectedTypeId] = 0; }); } };
二、后端实现(MVC5控制器上传方法)
后端需要接收文件集合和文档类型ID,同时做二次校验(防止前端限制被绕过),最后完成文件保存与关联:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; public class YourController : Controller { [HttpPost] public async Task<ActionResult> Upload(IEnumerable<HttpPostedFileBase> files, int LKP_DocType) { // 1. 校验文档类型合法性 var validDocTypeIds = new List<int> { 1, 2, 3 }; if (!validDocTypeIds.Contains(LKP_DocType)) { return Json(new { success = false, message = "无效的文档类型" }); } // 2. 校验总上传大小不超过5MB const long MaxTotalSize = 5 * 1024 * 1024; long totalUploadSize = files.Sum(f => f?.ContentLength ?? 0); if (totalUploadSize > MaxTotalSize) { return Json(new { success = false, message = "当前文档类型总上传大小不能超过5MB" }); } // 3. 逐个校验文件并保存 foreach (var file in files) { if (file == null || file.ContentLength == 0) continue; // 校验文件类型(MIME+扩展名双重校验更安全) if (file.ContentType != "application/pdf" || Path.GetExtension(file.FileName).ToLower() != ".pdf") { return Json(new { success = false, message = $"文件{file.FileName}不是合法的PDF格式" }); } // 校验单文件大小 if (file.ContentLength > MaxTotalSize) { return Json(new { success = false, message = $"文件{file.FileName}大小超过5MB限制" }); } // 处理文件名重复问题(用GUID生成唯一文件名) string uniqueFileName = $"{Guid.NewGuid()}_{Path.GetFileName(file.FileName)}"; string uploadPath = Path.Combine(Server.MapPath("~/Uploads"), uniqueFileName); // 确保上传目录存在 Directory.CreateDirectory(Path.GetDirectoryName(uploadPath)); // 保存文件到服务器 file.SaveAs(uploadPath); // 4. 关联文档类型到数据库(示例代码,根据你的实体调整) // var document = new Document // { // DocTypeId = LKP_DocType, // FileName = uniqueFileName, // FilePath = uploadPath, // UploadTime = DateTime.Now // }; // db.Documents.Add(document); // await db.SaveChangesAsync(); } return Json(new { success = true, message = "所有文件上传成功" }); } }
三、关键注意事项
- 权限配置:确保服务器上的
~/Uploads目录有读写权限,否则文件保存会失败。 - 文件名去重:用GUID拼接文件名避免覆盖已有文件,这是生产环境的必要操作。
- 双重校验:前端校验提升用户体验,后端校验保障数据安全,不可省略后端校验。
- 错误反馈:前端和后端都要返回清晰的错误提示,帮助用户定位问题。
内容的提问来源于stack exchange,提问作者Syed Mohsin
相关产品推荐
相关产品推荐

