多Dropzone.js实例文件上传异常:文件传入错误实例问题
问题描述
将旧版(2012年)Dropzone.js升级至最新版后,自定义PHP CMS的图片管理模块出现异常:页面上的多图片表单(支持Ajax动态添加)可正常展示,但上传文件时,文件会被错误分配到其他Dropzone实例。比如4个实例时,第1个实例的文件会传到第2个,其余实例的文件均传到第1个。
现有JavaScript代码
// INITIALISE DROPZONE $(".multi-dropzone").each(function(i, element) { // CHECK THERE ISN'T A DROPZONE ALREADY ON THERE if ($(this).get(0).dropzone) { return; } // GET THE IMAGE ID TO PASS INTO PROCESSING let imageid = $(this).data("imageid"); let pageid = $(this).data("pageid"); $(this).dropzone({ url: 'edit.php?id='+pageid+'&mode=update-image&img_id='+imageid, uploadMultiple: false, maxFilesize: 10, // 10MB parallelUploads: 1, clickable: '.dropzone', createImageThumbnails: false, dictFileTooBig: "File is too big ({{filesize}}MB). Max filesize: {{maxFilesize}}MB.", acceptedFiles: "image/*", init: function() { var self = this; // WHEN ADDING A FILE self.on('addedfile', function(file) { $(this).css("border", "solid red 2px"); console.log("Added file to Dropzone with image ID: " + imageid); // REMOVE OLD PREVIEW if ($(this.element).find('.dz-preview').length > 1) { $(this.element).find('.dz-preview').first().remove(); } }); // SUCCESSFULLY ADDED self.on('success', function(file, response) { // UPDATE HIDDEN IMAGE NAME alert(response); $(self.element).find('.img_name').val(response); }); } }); }); } // ENABLE ALL DROPZONES init_image_dropzones();
前端DOM示例(其中一个.page-image元素)
<form action="edit.php?id=1&mode=update-image-details&img_id=34" method="POST" id="img-34-form" class="image-form" enctype="multipart/form-data"> <div id="dropzone-34" class="dropzone multi-dropzone dz-clickable" data-pageid="1" data-imageid="img_34"> <input type="hidden" class="img_name" name="img" id="img" value=""> <!-- IMAGE PREVIEW --> <div class="dz-preview"> <div class="dz-image"> <img data-dz-thumbnail="" alt="Image description goes here..." src="/path/to/image.jpg"> </div> <div class="dz-details" data-dz-message=""> <div class="dz-message"> <p class="upload-image">Click image to update</p> </div> </div> </div> </div> <input type="text" id="title" name="title" class="textbox-blended image-title" value="Image Title Here..."> <input type="submit" id="submit" name="submit" class="submit-button circle-btn inline-submit" value="save"> </div> </form> <button id="delete-1-34" type="button" class="inline-delete circle-btn" data-parent-id="1" data-item-id="34"></button> </div>
升级前功能正常,现在通过浏览器检查发现Dropzone.js插入的4个隐藏文件域属性完全相同,无唯一标识关联对应实例。已加载最新版jQuery、jQuery UI和Dropzone.js。
问题原因与修复方案
核心问题
clickable选择器全局匹配:设置的clickable: '.dropzone'是全局类选择器,所有带.dropzone类的元素都会触发任意一个Dropzone实例的上传,这是文件串到其他实例的根本原因。- 回调上下文混淆:
addedfile回调中使用$(this)可能指向错误的上下文,而非当前Dropzone实例。 - 实例标识缺失:新版Dropzone对多实例的隔离要求更高,未给每个实例设置唯一标识或参数名,导致上传时无法区分归属。
修复步骤
1. 修正clickable选择器,绑定当前实例元素
把全局类选择器改为当前循环的DOM节点,确保每个Dropzone实例只响应自身容器的点击:
clickable: element, // 替换原来的'.dropzone'
2. 为每个实例设置唯一的文件参数名
新版Dropzone默认文件参数名为file,多实例同时存在时易混淆,结合imageid设置唯一参数名:
paramName: 'file_' + imageid,
3. 统一回调中的实例上下文
在init方法内,始终使用self(已赋值为当前实例)代替$(this),避免上下文错乱:
self.on('addedfile', function(file) { $(self.element).css("border", "solid red 2px"); // 用self.element指向当前实例容器 // ... 其他逻辑 });
4. 禁用Dropzone自动发现功能(可选)
如果页面存在未手动初始化的Dropzone,可能干扰现有实例,初始化前添加:
Dropzone.autoDiscover = false;
修复后的完整JavaScript代码
// 禁用自动发现,避免干扰手动实例 Dropzone.autoDiscover = false; // INITIALISE DROPZONES function init_image_dropzones() { $(".multi-dropzone").each(function(i, element) { // 检查是否已存在Dropzone实例 if (element.dropzone) { return; } // 获取当前实例的ID参数 let imageid = $(this).data("imageid"); let pageid = $(this).data("pageid"); $(this).dropzone({ url: 'edit.php?id='+pageid+'&mode=update-image&img_id='+imageid, uploadMultiple: false, maxFilesize: 10, // 10MB parallelUploads: 1, clickable: element, // 绑定当前实例的元素 paramName: 'file_' + imageid, // 唯一文件参数名 createImageThumbnails: false, dictFileTooBig: "File is too big ({{filesize}}MB). Max filesize: {{maxFilesize}}MB.", acceptedFiles: "image/*", init: function() { var self = this; self.on('addedfile', function(file) { $(self.element).css("border", "solid red 2px"); console.log("Added file to Dropzone with image ID: " + imageid); // 移除旧预览 if ($(self.element).find('.dz-preview').length > 1) { $(self.element).find('.dz-preview').first().remove(); } }); self.on('success', function(file, response) { alert(response); $(self.element).find('.img_name').val(response); }); } }); }); } // 启用所有Dropzones init_image_dropzones();
内容的提问来源于stack exchange,提问作者Scott Richardson
相关产品推荐
相关产品推荐

