Интеграция Dropzone.js в существующую HTML-форму с другими полями

В настоящее время у меня есть HTML-форма, в которой пользователи заполняют детали объявления, которое они хотят опубликовать. Теперь я хочу иметь возможность добавить dropzone для загрузки изображений товара для продажи. Я нашел dropzone.js, который, кажется, делает большую часть того, что мне нужно. Однако при просмотре документации вы должны указать класс всей формы как "dropzone" (в отличие от только элемента ввода). Это значит, что вся моя форма становится dropzone. Можно ли использовать dropzone только в части моей формы, т.е. Указывая только элемент как класс dropzone, а не всю форму?

Я мог бы использовать отдельные формы, но я хочу, чтобы пользователь мог отправить все это с помощью одной кнопки.

Кроме того, есть ли другая библиотека, которая может это сделать?

Большое спасибо

Ответ 1

Вот еще один способ сделать это: добавьте div в свою форму с помощью dropzone класса и программно создайте 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");
        }
    });
});

Примечание. Отключение автосохранения, в противном случае Dropzone попытается дважды вставить

Статья в блоге: Dropzone js + Asp.net: простой способ загрузки массовых изображений

Ответ 2

У меня была такая же проблема, и я обнаружил, что ответ Варана Синайи был единственным, кто фактически решил исходный вопрос. Однако этот ответ можно упростить, поэтому здесь более простая версия.

Шаги:

  • Создайте нормальную форму (не забывайте, что метод и enctype args, поскольку это больше не обрабатывается dropzone).

  • Поместите div внутри с помощью class="dropzone" (с тем, как Dropzone присоединяется к нему) и id="yourDropzoneName" (используется для изменения параметров).

  • Задайте параметры Dropzone, чтобы установить URL-адрес, где будут размещаться форма и файлы, деактивировать autoProcessQueue (так что это происходит только тогда, когда пользователь нажимает "submit" ) и разрешает несколько загрузок (если вам это нужно).

  • Задайте функцию init для использования Dropzone вместо поведения по умолчанию при нажатии кнопки отправки.

  • Все еще в функции init используйте обработчик событий "sendmultiple" для отправки данных формы вместе с файлами.

Войла! Теперь вы можете получить данные, как в обычной форме, в $_POST и $_FILES (в примере это произойдет в upload.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());
        });
    }
}

Ответ 3

"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." });
    }

Ответ 4

Enyo tutorial отлично.

Я обнаружил, что образец script в учебнике хорошо работает для кнопки, встроенной в dropzone (т.е. элемент формы). Если вы хотите, чтобы кнопка вне элемента формы, я смог выполнить ее с помощью события click:

Во-первых, 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>

Затем тег script....

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 the change from enyo tutorial...

        $("#submit-all").click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            myDropzone.processQueue();
        }); 
    }
}

Ответ 5

В дополнение к тому, что говорил sqram, у Dropzone есть дополнительный недокументированный параметр "hiddenInputContainer". Все, что вам нужно сделать, это установить этот параметр в селектор формы, к которой вы хотите добавить скрытое поле файла. И вуаля! Поле ".dz-hidden-input", которое Dropzone обычно добавляет к телу, волшебным образом перемещается в вашу форму. Не изменяйте исходный код Dropzone.

Теперь, когда это работает, чтобы переместить поле файла Dropzone в вашу форму, поле не имеет имени. Поэтому вам нужно будет добавить:

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

для dropzone.js после этой строки:

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

вокруг линии 547.

Ответ 6

У меня есть более автоматизированное решение для этого.

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");
    }
}

Laravel:

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

Нет необходимости отключать DiscZone Discovery, и нормальная форма submit сможет отправлять файл с любыми другими полями формы через стандартную сериализацию форм.

Этот механизм сохраняет содержимое файла в качестве строки base64 в скрытом поле ввода при его обработке. Вы можете декодировать его обратно в двоичную строку в PHP с помощью стандартного base64_decode().

Я не знаю, будет ли этот метод скомпрометирован большими файлами, но он работает с файлами ~ 40 МБ.

Ответ 7

Вы можете изменить formData, поймав событие "отправка" из вашей dropzone.

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

Ответ 8

Чтобы отправить все файлы вместе с другими данными формы в один запрос, вы можете скопировать временные скрытые узлы input Dropzone.js в вашу форму. Вы можете сделать это в обработчике событий 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);
});

Obviosly - это обходное решение, зависящее от деталей реализации. Связанный исходный код.

Ответ 9

Это еще один пример того, как вы можете использовать Dropzone.js в существующей форме.

dropzone.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 +'">');
}

Это предполагает, что у вас есть div с id #botofform таким образом, при загрузке вы можете использовать имена загруженных файлов.

Примечание: моя загрузка script возвратила значение theuploadedfilename.jpeg dubblenote вам также понадобится очистить script, который проверяет каталог загрузки для файлов, которые не используются, и удаляет их. if в не прошедшей аутентификацию форме:)

Ответ 10

Вот мой пример, основанный на 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>

Ответ 11

У меня проблема с переключателями. Все остальные типы ввода в моей форме передают правильные значения, но переключатели отправляют значение первой опции. Почему бы Dropzone не взять проверенное значение? Я пробовал несколько способов получить проверенное значение, но ни один из них не сработал.

@Html.RadioButtonFor(m => m.SubClient, "ForeSite Services, Inc.") &nbsp;&nbsp;&nbsp; ForeSite Services, Inc.<br />
                    @Html.RadioButtonFor(m => m.SubClient, "High Performance Services") &nbsp;&nbsp;&nbsp; High Performance Services<br />
                    @Html.RadioButtonFor(m => m.SubClient, "Southernlink Consulting, LLC") &nbsp;&nbsp;&nbsp; Southernlink Consulting, LLC<br />

Ответ 12

Я хочу внести здесь ответ, поскольку я тоже столкнулся с той же проблемой - мы хотим, чтобы элемент $ _FILES был доступен как часть той же публикации, что и другая форма. Мой ответ основан на @mrtnmgs, но отмечает комментарии, добавленные к этому вопросу.

Во-первых: Dropzone публикует свои данные через ajax

То, что вы используете опцию formData.append, по-прежнему означает, что вы должны выполнять действия UX - то есть все это происходит за кулисами и не является типичной формой публикации. Данные публикуются в ваш параметр url.

Во-вторых: если вы хотите имитировать форму сообщения, вам нужно будет сохранить опубликованные данные

Для этого требуется код на стороне сервера, чтобы сохранить ваши $_POST или $_FILES в сеансе, который доступен пользователю при загрузке другой страницы, поскольку пользователь не будет переходить на страницу, на которой получены опубликованные данные.

В-третьих: вам нужно перенаправить пользователя на страницу, где действуют эти данные

Теперь вы разместили свои данные, сохранили их в сеансе, вам нужно отобразить/обработать их для пользователя на дополнительной странице. Вам также необходимо отправить пользователя на эту страницу.

Итак, для моего примера:

[Код Dropzone: использует 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';
        })
    },
});