Dropzone.js'yi diğer alanlarla mevcut HTML formuna entegre etme


181

Şu anda kullanıcıların göndermek istedikleri bir reklamın ayrıntılarını doldurdukları bir HTML formum var. Şimdi satılık öğenin resimlerini yüklemek için bir dropzone eklemek istiyorum .

İhtiyacımın çoğunu yapıyor gibi görünen Dropzone.js'yi buldum . Bununla birlikte, belgelere bakarken, tüm formun sınıfını ( dropzoneyalnızca giriş öğesinin aksine) olarak belirtmeniz gerektiği görülmektedir . Bu, tüm formumun dropzone olduğu anlamına gelir .

Dropzone'u formumun sadece bir bölümünde kullanmak, yani öğeyi tüm form yerine yalnızca "dropzone" sınıfı olarak belirtmek mümkün mü?

Ayrı formlar kullanabilirim, ancak kullanıcının hepsini tek bir düğmeyle gönderebilmesini istiyorum.

Alternatif olarak, bunu yapabilen başka bir kütüphane var mı?

Çok teşekkürler

Yanıtlar:


59

İşte bunu yapmanın başka bir yolu: divdropzone sınıf adıyla formunuza a ekleyin ve dropzone'u programlı olarak uygulayın.

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

Not: autoDiscover'ı devre dışı bırakmak, aksi takdirde Dropzone iki kez eklemeye çalışır

Blog Yazısı : Dropzone js + Asp.net: Toplu resimleri yüklemenin kolay yolu


25
Bunu dedikten varsayılan gönderme düğmesini kullanamazsınız, onun soru yanıt vermez
clement

5
ancak bu hala göndermek için orijinal formu kullanmaz
dangel

3
bu benim sorunum ve çözdünüz, ty @Satindersingh
Su4p

1
@ Su4p: size yardımcı olduğu için memnunum, ayrıca yükleme sırasında yeniden boyutlandırma seçeneği ile birlikte ayrıntı açıklaması için blog makalesi bağlantısını kontrol edebilirsiniz
Satinder singh

2
Bu çok yardımcı oldu, url'yi manuel olarak ayarlarsanız herhangi bir öğeyi dropzone olarak ayarlayabilirsiniz. Birincil formdaki gizli / devre dışı bir alana dosya adını göndermek için başarı işleyicisini kullandım.
DigitalDesignDj

40

Aynı problemi yaşadım ve Varan Sinayee'nin cevabının orijinal soruyu gerçekten çözen tek cevap olduğunu buldum. Bu cevap basitleştirilebilir, bu yüzden burada daha basit bir sürüm var.

Adımlar:

  1. Normal bir form oluşturun (artık dropzone tarafından işlenmediği için yöntemi unutmayın ve argümanları şifreleyin).

  2. class="dropzone"(Dropzone bu şekilde eklenir) ve id="yourDropzoneName"(seçenekleri değiştirmek için kullanılır ) içine bir div koyun .

  3. Formun ve dosyaların gönderileceği URL'yi ayarlamak için Dropzone'un seçeneklerini ayarlayın, autoProcessQueue özelliğini devre dışı bırakın (bu nedenle yalnızca kullanıcı 'gönder'e bastığında olur) ve birden fazla yüklemeye izin verir (gerekirse).

  4. İnit işlevini, gönder düğmesi tıklatıldığında varsayılan davranış yerine Dropzone kullanacak şekilde ayarlayın.

  5. Yine de init işlevinde, form verilerini dosyalarla birlikte göndermek için "sendingmultiple" olay işleyicisini kullanın.

Voilà! Artık normal bir formda olduğu gibi verileri $ _POST ve $ _FILES biçiminde alabilirsiniz (örnekte bu upload.php'de olurdu)

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

1
Bu çözüm güzel ve işe yarıyor, ancak varsayılan gönderme davranışını engellediği için bir sonraki sayfaya yönlendirmiyor.
Felix G.12

@TIIUNDER - sayfa yeniden yüklemeden ajax çağrısı yoluyla form bilgisi göndermek için hazırlanmıştır - bu yüzden e.preventDefault ();
born2fr4g

1
@TIUNDER, başarı etkinliğine yönlendirme ekleyebilirsiniz
doflamingo

Çağrıdan sonra formu göndermek mümkün mü processQueue()? Kullanmaya çalışıyorum submit()ya da click()her ikisi de çalışmıyor.
Gray Li

1
+1 Bu tek çalışan çözüm gibi görünüyor. FormData.append'i tek tek yapmak yerine, şunları da yapabilirsiniz $(":input[name]", $("form")).each(function () { formData.append(this.name, $(':input[name=' + this.name + ']', $("form")).val()); }); (üzgünüm, buraya
çizgi satırlarını

20

"Dropzone.js" resim yüklemek için en yaygın kütüphanedir. "Dropzone.js" nin yalnızca formunuzun bir parçası olmasını istiyorsanız, aşağıdaki adımları gerçekleştirmelisiniz:

1) müşteri tarafı için:

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) sunucu tarafı için:

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

2
Gönderi için teşekkürler! Sorunumu çözdüm. Başka bir hızlı soru, hiçbir resim seçilmediğinde (yüklenmek için) çalışmıyor, nasıl çözülür?
Sato

BTW: Model bağlama ile denetleyici eylemi kullanır ve formunuzu bu şekilde gönderirseniz model boş olacaktır. Bazı nedenlerden dolayı bu yöntem gerçek verileri modele bağlamaz.
Edward Chopuryan

1
autoProcessQueue = false olduğunda hiçbir olay tetiklenmez
cyril

Gönder düğmesi tıklandığında @Sato, galleryfile.getAcceptedFiles (). Uzunluğunu kullanarak dropzone üzerindeki kabul edilen dosyaların uzunluğunu kontrol edebilir ve yüklenen dosya yoksa formunuzu göndermelisiniz.
Varan Sinayee

@EdwardChopuryan Bu, dropzone tarafından veri gönderme yöntemiyle ilgili değildir. Muhtemelen sorun ASP.Net MVC gibi platformunuzdaki giriş etiketlerinin "adlandırma kuralı" üzerindedir.
Varan Sinayee

11

Enyo'nun eğitimi mükemmel.

Ben öğretici örnek komut dosyası dropzone (yani, form öğesi) gömülü bir düğme için iyi çalıştı bulundu. Düğmenin form öğesinin dışında olmasını istiyorsanız, bir click olayını kullanarak başarabildim:

İlk olarak, 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>

Sonra, komut dosyası etiketi ....

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

23
Bir form içinde form gönderemez ve gönderemezsiniz.
paul

1
Bunu denediğimde, dropzone-önizleme kabı yok sayılıyor gibi görünüyor. Dropzone sadece önizlemeleri formun altına ekler. Yapılandırmanıza 'previewsContainer:' .dropzone-previews ',' eklemeniz gerekecek.
Aaron Hill

6
Bu asıl soruya cevap vermiyor. Orijinal soru, eylemi tetiklemek için düğmenin yeri hakkında değil, Dropzone'un mevcut bir formla nasıl kullanılacağıydı.
CSSian

7

Sqram'ın söylediklerine ek olarak, Dropzone'un ek bir belgesiz seçeneği "hiddenInputContainer" vardır. Tek yapmanız gereken bu seçeneği gizli dosya alanının eklenmesini istediğiniz formun seçicisine ayarlamaktır. Ve işte! Dropzone'un normalde gövdeye eklediği ".dz-hidden-input" dosya alanı sihirli bir şekilde formunuza taşınır. Dropzone kaynak kodunu değiştirmeye gerek yok.

Artık bu, Dropzone dosya alanını formunuza taşımak için çalışırken, alanın adı yoktur. Bu yüzden eklemeniz gerekecek:

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

Bu satırdan sonra dropzone.js'ye:

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

547 hattı civarında.


5

Bunun için daha otomatik bir çözümüm var.

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'));

DropZone Discovery'yi devre dışı bırakmanıza gerek yoktur ve normal form gönderme, dosyayı standart form serileştirme yoluyla başka herhangi bir form alanıyla gönderebilir.

Bu mekanizma dosya içeriğini işlendiğinde gizli girdi alanında base64 dizesi olarak saklar. Standart base64_decode()yöntemle PHP'deki ikili dizgiye deşifre edebilirsiniz .

Bu yöntemin büyük dosyalarla tehlikeye girip girmeyeceğini bilmiyorum ama ~ 40MB dosyalarıyla çalışıyor.


Resimlerle birlikte gönderilecek diğer alanlardaki verileri nasıl çözer ve işler?
sam

@sam Diğer alanların kodunu çözmeye gerek yoktur. İlk etapta kodlanmıyorlar, sadece dosya kodlanıyor.
Umair Ahmed

Html, javascript ve nasıl laravel php almak için bazı örnek kod paylaşabilirsiniz.
sam

2
Birden fazla görüntü eklemek istiyorsanız, html dosya girişini kaldırmanız ve her görüntü için js sorgulaması eklemeniz gerekir $ ('# fileUpload'). Append ('<input hidden name = "files []" value =' + content + ' /> ') içeriğin base64 kodlu görüntü olduğu durumlarda.
AleXzpm

1
@codepushr iyi onun ücretli çözümler düşünmüyordu zaman eski bir cevap. Şimdi FileUploader'ı satın aldık, ancak kendi parlaklığı olmasına rağmen, neredeyse her şeyi yapmak için özelleştirilebileceğini söylemek yeterli.
Umair Ahmed

4

FormData'yı, dropzone'unuzdaki 'gönderme' olayını yakalayarak değiştirebilirsiniz.

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

1
Bu yanıtı beğendim - ancak alan adı ve değerin doldurulduğunu varsayar. Bu, form gönderme işleminden ayrı bir zamanda gerçekleşebilecek yükleme işleminde tetiklenir. Diğer bir deyişle, resmi gönderirken formun doldurulduğunu varsayamazsınız.
Antony

4

Diğer form verilerinin yanı sıra tüm dosyaları tek bir istekte göndermek için Dropzone.js geçici gizli inputdüğümlerini formunuza kopyalayabilirsiniz . Bunu addedfilesolay işleyici içinde yapabilirsiniz :

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

Açıkçası bu, uygulama ayrıntılarına bağlı bir çözümdür. İlgili kaynak kodu .


Temelde bu yaklaşımı kullandım, ancak görünen işleme gecikmeleri nedeniyle, sonunda dosya içeriği işlemeyi myDropzone.on("thumbnail", () => {})olay altında bağladım . İşlemin hemen "addedFile"dosya undefinedüzerinde yapılması erişim sağlanmış olabilir .
Matti

Bunu kullanmaya çalışıyorum ve gizli dosya giriş alanı forma getirerek çalışır ve ben göndermek, yazı veri alanımı gösterir files[]ama ne olursa olsun boş. Herhangi bir fikir? Herhangi bir fark yaratırsa Laravel'de yapmak.
zen

Merhaba! Seçilen dosya neden yükleniyor ancak dosya düşürülürse yüklenmiyor (hata 4)?
Ingus

2

Ben de aynı sorunla karşı karşıya olduğum için burada bir cevap vermek istiyorum - $ _FILES eleman başka bir form gibi aynı yazı bir parçası olarak kullanılabilir istiyoruz. Cevabım mrtnmgs'e dayanıyor, ancak bu soruya eklenen yorumları not ediyor.

İlk olarak: Dropzone verilerini ajax aracılığıyla yayınlar

formData.appendSeçeneği hala kullanmanız, UX eylemleriyle uğraşmanız gerektiği anlamına gelir - yani bunların hepsi perde arkasında gerçekleşir ve tipik bir form gönderisi değildir. Veriler urlparametrenize gönderilir .

İkincisi: Bu nedenle bir form gönderisini taklit etmek istiyorsanız, kaydedilen verileri depolamanız gerekir

Bu , kullanıcı tarafından gönderilen verilerin alındığı sayfaya gitmeyeceğinden, kullanıcı tarafından başka bir sayfa yüklemesinde kullanılabilen bir oturumda $_POSTveya $_FILESoturumda sunucu tarafı kodunun saklanmasını gerektirir .

Üçüncüsü: Kullanıcıyı bu verilerin işlendiği sayfaya yönlendirmeniz gerekir

Şimdi verilerinizi bir oturumda yayınladınız, kullanıcı için ek bir sayfada görüntülemeniz / işlemeniz gerekiyor. Kullanıcıyı bu sayfaya da göndermeniz gerekir.

Benim örneğim için:

[Dropzone kodu: Jquery kullanır]

$('#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';
        })
    },
});

1

Bu, Dropzone.js'yi mevcut bir biçimde nasıl kullanabileceğinizin başka bir örneğidir.

dropzone.js:

 init: function() {

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

   return noop;
 },

Sonra, daha sonra dosyaya koydum

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

Bu #botofform, yükleme sırasında kimliğe sahip bir div bulunduğunu varsayar ve yüklenen dosyaların adlarını kullanabilirsiniz.

Not: Yükleme komut dosyam, theuploadedfilename.jpeg dubblenote'u döndürdü, ayrıca kullanımda olmayan dosyalar için yükleme dizinini kontrol eden ve bunları silen bir ön temizleme komut dosyası oluşturmanız gerekir.


Bu, dropzone görüntülerini diğer form alanlarıyla birlikte göndermez. Yaptığınız şey görüntüleri normal olarak yüklemek, görüntü adlarını kaydetmek ve daha sonra form alanlarının geri kalanını görüntü adlarıyla yeniden göndermektir.
zen

1

İşte benim örnek, Django + Dropzone dayanmaktadır. Görünüm seçti (gerekli) ve gönderdi.

<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>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.