将 Dropzone.js 集成到与其他字段的现有 HTML 表单中

Integrating Dropzone.js into existing HTML form with other fields

本文关键字:HTML 表单 字段 其他 js Dropzone 集成      更新时间:2023-09-26

我目前有一个HTML表单,用户可以填写他们希望发布的广告的详细信息。我现在希望能够添加一个拖放区,用于上传待售商品的图像。

我找到了Dropzone.js它似乎可以满足我的大部分需求。但是,在查看文档时,似乎需要将整个表单的类指定为dropzone(而不仅仅是输入元素(。这意味着我的整个表单都变成了拖放区

是否可以仅在我的表单的一部分中使用拖放区,即仅将元素指定为类"dropzone">,而不是整个表单?

我可以使用单独的表单,但我希望用户能够通过一个按钮提交所有表单。

或者,是否有其他库可以做到这一点?

非常感谢

这是另一种方法:使用类名 dropzone 在窗体中添加一个div,并以编程方式实现 dropzone。

.HTML:

<div id="dZUpload" class="dropzone">
      <div class="dz-default dz-message"></div>
</div>

JQuery:

$(document).ready(function () {
    Dropzone.autoDiscover = false;
    $("#dZUpload").dropzone({
        url: "hn_SimpeFileUploader.ashx",
        addRemoveLinks: true,
        success: function (file, response) {
            var imgName = response;
            file.previewElement.classList.add("dz-success");
            console.log("Successfully uploaded :" + imgName);
        },
        error: function (file, response) {
            file.previewElement.classList.add("dz-error");
        }
    });
});

注意:禁用自动发现,否则拖放区将尝试附加两次

我遇到了完全相同的问题,发现Varan Sinayee的答案是唯一真正解决原始问题的答案。不过,这个答案可以简化,所以这里有一个更简单的版本。

步骤如下:

  1. 创建一个普通表单(不要忘记方法和 enctype args,因为这不再由 dropzone 处理(。

  2. 将div 与class="dropzone"(这就是 Dropzone 附加到它的方式(和 id="yourDropzoneName"(用于更改选项(放在里面。

  3. 设置Dropzone的选项,以设置将发布表单和文件的URL,停用autoProcessQueue(因此仅在用户按"提交"时发生(并允许多次上传(如果需要(。

  4. 将 init 函数设置为在单击提交按钮时使用拖放区而不是默认行为。

  5. 仍然在 init 函数中,使用"发送多个"事件处理程序将表单数据与文件一起发送。

瞧!您现在可以像使用普通表单一样检索数据,以 $_POST 和 $_FILES 为单位(在示例中,这将发生在上传.php(

.HTML

<form action="upload.php" enctype="multipart/form-data" method="POST">
    <input type="text" id ="firstname" name ="firstname" />
    <input type="text" id ="lastname" name ="lastname" />
    <div class="dropzone" id="myDropzone"></div>
    <button type="submit" id="submit-all"> upload </button>
</form>

.JS

Dropzone.options.myDropzone= {
    url: 'upload.php',
    autoProcessQueue: false,
    uploadMultiple: true,
    parallelUploads: 5,
    maxFiles: 5,
    maxFilesize: 1,
    acceptedFiles: 'image/*',
    addRemoveLinks: true,
    init: function() {
        dzClosure = this; // Makes sure that 'this' is understood inside the functions below.
        // for Dropzone to process the queue (instead of default form behavior):
        document.getElementById("submit-all").addEventListener("click", function(e) {
            // Make sure that the form isn't actually being sent.
            e.preventDefault();
            e.stopPropagation();
            dzClosure.processQueue();
        });
        //send all the form data along with the files:
        this.on("sendingmultiple", function(data, xhr, formData) {
            formData.append("firstname", jQuery("#firstname").val());
            formData.append("lastname", jQuery("#lastname").val());
        });
    }
}

"dropzone.js"是上传图像的最常见库。如果您希望将"dropzone.js"作为表单的一部分,则应执行以下步骤:

1(对于客户端:

.HTML:

    <form action="/" enctype="multipart/form-data" method="POST">
        <input type="text" id ="Username" name ="Username" />
        <div class="dropzone" id="my-dropzone" name="mainFileUploader">
            <div class="fallback">
                <input name="file" type="file" multiple />
            </div>
        </div>
    </form>
    <div>
        <button type="submit" id="submit-all"> upload </button>
    </div>

JQuery:

    <script>
        Dropzone.options.myDropzone = {
            url: "/Account/Create",
            autoProcessQueue: false,
            uploadMultiple: true,
            parallelUploads: 100,
            maxFiles: 100,
            acceptedFiles: "image/*",
            init: function () {
                var submitButton = document.querySelector("#submit-all");
                var wrapperThis = this;
                submitButton.addEventListener("click", function () {
                    wrapperThis.processQueue();
                });
                this.on("addedfile", function (file) {
                    // Create the remove button
                    var removeButton = Dropzone.createElement("<button class='btn btn-lg dark'>Remove File</button>");
                    // Listen to the click event
                    removeButton.addEventListener("click", function (e) {
                        // Make sure the button click doesn't submit the form:
                        e.preventDefault();
                        e.stopPropagation();
                        // Remove the file preview.
                        wrapperThis.removeFile(file);
                        // If you want to the delete the file on the server as well,
                        // you can do the AJAX request here.
                    });
                    // Add the button to the file preview element.
                    file.previewElement.appendChild(removeButton);
                });
                this.on('sendingmultiple', function (data, xhr, formData) {
                    formData.append("Username", $("#Username").val());
                });
            }
        };
    </script>

2(对于服务器端:

ASP.Net MVC

    [HttpPost]
    public ActionResult Create()
    {
        var postedUsername = Request.Form["Username"].ToString();
        foreach (var imageFile in Request.Files)
        {
        }
        return Json(new { status = true, Message = "Account created." });
    }

我有一个更自动化的解决方案。

.HTML:

<form role="form" enctype="multipart/form-data" action="{{ $url }}" method="{{ $method }}">
    {{ csrf_field() }}
    <!-- You can add extra form fields here -->
    <input hidden id="file" name="file"/>
    <!-- You can add extra form fields here -->
    <div class="dropzone dropzone-file-area" id="fileUpload">
        <div class="dz-default dz-message">
            <h3 class="sbold">Drop files here to upload</h3>
            <span>You can also click to open file browser</span>
        </div>
    </div>
    <!-- You can add extra form fields here -->
    <button type="submit">Submit</button>
</form>

JavaScript:

Dropzone.options.fileUpload = {
    url: 'blackHole.php',
    addRemoveLinks: true,
    accept: function(file) {
        let fileReader = new FileReader();
        fileReader.readAsDataURL(file);
        fileReader.onloadend = function() {
            let content = fileReader.result;
            $('#file').val(content);
            file.previewElement.classList.add("dz-success");
        }
        file.previewElement.classList.add("dz-complete");
    }
}

拉拉维尔:

// Get file content
$file = base64_decode(request('file'));

无需禁用 DropZone 发现,正常的表单提交将能够通过标准表单序列化将文件与任何其他表单字段一起发送。

此机制在处理文件内容时将文件内容作为 base64 字符串存储在隐藏的输入字段中。您可以通过标准的 base64_decode() 方法将其解码回 PHP 中的二进制字符串。

我不知道这种方法是否会受到大文件的影响,但它适用于~40MB文件。

Enyo的教程非常出色。

我发现教程中的示例脚本适用于嵌入在拖放区中的按钮(即表单元素(。如果您希望将按钮放在表单元素之外,我可以使用单击事件来完成它:

首先,HTML :

<form id="my-awesome-dropzone" action="/upload" class="dropzone">  
    <div class="dropzone-previews"></div>
    <div class="fallback"> <!-- this is the fallback if JS isn't working -->
        <input name="file" type="file" multiple />
    </div>
</form>
<button type="submit" id="submit-all" class="btn btn-primary btn-xs">Upload the file</button>

然后,脚本标记....

Dropzone.options.myAwesomeDropzone = { // The camelized version of the ID of the form element
    // The configuration we've talked about above
    autoProcessQueue: false,
    uploadMultiple: true,
    parallelUploads: 25,
    maxFiles: 25,
    // The setting up of the dropzone
    init: function() {
        var myDropzone = this;
        // Here's the change from enyo's tutorial...
        $("#submit-all").click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            myDropzone.processQueue();
        }); 
    }
}

除了sqram所说的之外,Dropzone还有一个额外的未记录选项,"hiddenInputContainer"。 您所要做的就是将此选项设置为您希望附加隐藏文件字段的表单的选择器。 瞧! Dropzone 通常添加到正文中的".dz-hidden-input"文件字段会神奇地移动到您的表单中。 不更改拖放区源代码。

现在,虽然这可以将拖放区文件字段移动到表单中,但该字段没有名称。 因此,您需要添加:

_this.hiddenFileInput.setAttribute("name", "field_name[]");

到拖放区.js在此行之后:

_this.hiddenFileInput = document.createElement("input");

在 547 行附近。

我想

在这里提供一个答案,因为我也遇到了同样的问题 - 我们希望 $_FILES 元素作为另一个表单同一帖子的一部分提供。我的回答是基于@mrtnmgs但是注意到添加到该问题的评论。

首先:Dropzone通过ajax发布其数据

仅仅因为您使用formData.append选项仍然意味着您必须处理 UX 操作 - 即这一切都发生在幕后,而不是典型的表单发布。 数据将发布到您的url参数。

其次:因此,如果您想模仿表单帖子,则需要存储发布的数据

这需要服务器端代码将您的$_POST$_FILES存储在会话中,该会话在另一个页面加载时可供用户使用,因为用户不会转到接收已发布数据的页面。

第三:您需要将用户重定向到处理此数据的页面

现在您已经发布了数据,将其存储在会话中,您需要在附加页面中为用户显示/操作它。您还需要将用户发送到该页面。

所以对于我的例子:

[拖放区代码:使用Jquery]

$('#dropArea').dropzone({
    url:        base_url+'admin/saveProject',
    maxFiles:   1,
    uploadMultiple: false,
    autoProcessQueue:false,
    addRemoveLinks: true,
    init:       function(){
        dzClosure = this;
        $('#projectActionBtn').on('click',function(e) {
            dzClosure.processQueue(); /* My button isn't a submit */
        });
        // My project only has 1 file hence not sendingmultiple
        dzClosure.on('sending', function(data, xhr, formData) {
            $('#add_user input[type="text"],#add_user textarea').each(function(){
                formData.append($(this).attr('name'),$(this).val());
            })
        });
        dzClosure.on('complete',function(){
            window.location.href = base_url+'admin/saveProject';
        })
    },
});

您可以通过从拖放区捕获"发送"事件来修改表单数据。

dropZone.on('sending', function(data, xhr, formData){
        formData.append('fieldname', 'value');
});

为了在单个请求中提交所有文件以及其他表单数据,您可以将 Dropzone.js临时隐藏input节点复制到表单中。您可以在addedfiles事件处理程序中执行此操作:

var myDropzone = new Dropzone("myDivSelector", { url: "#", autoProcessQueue: false });
myDropzone.on("addedfiles", () => {
  // Input node with selected files. It will be removed from document shortly in order to
  // give user ability to choose another set of files.
  var usedInput = myDropzone.hiddenFileInput;
  // Append it to form after stack become empty, because if you append it earlier
  // it will be removed from its parent node by Dropzone.js.
  setTimeout(() => {
    // myForm - is form node that you want to submit.
    myForm.appendChild(usedInput);
    // Set some unique name in order to submit data.
    usedInput.name = "foo";
  }, 0);
});

显然,这是一种取决于实现细节的解决方法。相关源代码。

5.7.0 版本的工作解决方案

<form id="upload" enctype="multipart/form-data">
    <input type="text" name="name" value="somename">
    <input type="checkbox" name="terms_agreed">
    <div id="previewsContainer" class="dropzone">
      <div class="dz-default dz-message">
        <button class="dz-button" type="button">
          Drop files here to upload
        </button>
      </div>
    </div>
    <input id="dz-submit" type="submit" value="submit">
</form>
Dropzone.autoDiscover = false;
new Dropzone("#upload",{
      clickable: ".dropzone",
      url: "upload.php",
      previewsContainer: "#previewsContainer",
      uploadMultiple: true,
      autoProcessQueue: false,
      init() {
        var myDropzone = this;
        this.element.querySelector("[type=submit]").addEventListener("click", function(e){
          e.preventDefault();
          e.stopPropagation();
          myDropzone.processQueue();
        });
      }
    });

这是我的示例,基于 Django + Dropzone。查看已选择(必填(并提交。

<form action="/share/upload/" class="dropzone" id="uploadDropzone">
    {% csrf_token %}
        <select id="warehouse" required>
            <option value="">Select a warehouse</option>
                {% for warehouse in warehouses %}
                    <option value={{forloop.counter0}}>{{warehouse.warehousename}}</option>
                {% endfor %}
        </select>
    <button id="submit-upload btn" type="submit">upload</button>
</form>
<script src="{% static '/js/libs/dropzone/dropzone.js' %}"></script>
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script>
    var filename = "";
    Dropzone.options.uploadDropzone = {
        paramName: "file",  // The name that will be used to transfer the file,
        maxFilesize: 250,   // MB
        autoProcessQueue: false,
        accept: function(file, done) {
            console.log(file.name);
            filename = file.name;
            done();    // !Very important
        },
        init: function() {
            var myDropzone = this,
            submitButton = document.querySelector("[type=submit]");
            submitButton.addEventListener('click', function(e) {
                var isValid = document.querySelector('#warehouse').reportValidity();
                e.preventDefault();
                e.stopPropagation();
                if (isValid)
                    myDropzone.processQueue();
            });
            this.on('sendingmultiple', function(data, xhr, formData) {
                formData.append("warehouse", jQuery("#warehouse option:selected").val());
            });
        }
    };
</script>

这只是如何在现有表单中使用 Dropzone.js 的另一个示例。

拖放区.js :

 init: function() {
   this.on("success", function(file, responseText) {
     //alert("HELLO ?" + responseText); 
     mylittlefix(responseText);
   });
   return noop;
 },

然后,稍后在我放的文件中

function mylittlefix(responseText) {
  $('#botofform').append('<input type="hidden" name="files[]" value="'+ responseText +'">');
}

这假设您有一个 id 的div #botofform这样上传时您就可以使用上传的文件的名称。

注意:我的上传脚本返回了上传的文件名.jpegDubblenote您还需要创建一个清理脚本,该脚本检查上传目录中未使用的文件并将其删除。如果在前端未经身份验证的表单中:)

试试这个

<div class="dropzone dz-clickable" id="myDrop">
  <div class="dz-default dz-message" data-dz-message="">
    <span>Drop files here to upload</span>
  </div>
</div>

.JS

<script>
    Dropzone.autoDiscover = false;
    Dropzone.default.autoDiscover=false;
    $("div#myDrop").dropzone({
        url: "/file/post",
    });
</script>