Dropzone.jsを他のフィールドを含む既存のHTMLフォームに統合する


181

私は現在、ユーザーが投稿したい広告の詳細を入力するHTMLフォームを持っています。販売する商品の画像をアップロードするためのドロップゾーンを追加できるようになりました。

Dropzone.jsが見つかりました。これは、必要なことのほとんどを実行しているようです。ただし、ドキュメントを見ると、dropzoneinput要素だけではなく)フォーム全体のクラスを指定する必要があるようです。これは、私のフォーム全体がドロップゾーンになることを意味します。

フォーム全体ではなく、クラスの「dropzone」として要素を指定するだけで、フォームの一部のみでドロップゾーンを使用することはできますか?

別のフォームを使用することもできますが、ユーザーが1つのボタンですべてを送信できるようにしたいと考えています。

または、これを実行できる別のライブラリはありますか?

どうもありがとう

回答:


59

これを行う別の方法は次のとおりです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");
        }
    });
});

注:autoDiscoverを無効にします。無効にしないと、Dropzoneが2回アタッチしようとします

ブログ記事Dropzone js + Asp.net:一括画像をアップロードする簡単な方法


25
それでは、彼はデフォルトの送信ボタンを使用できず、それは彼の質問に応答しません
クレメント

5
しかし、これはまだ元のフォームを使用して送信していません
dangel

3
これは私の問題であり、あなたはそれを解決しました、ty @Satindersingh
Su4p

1
@ Su4p:それがあなたを助けてくれてうれしいです。また、アップロード中の画像のサイズ変更オプションと一緒に詳細な説明についてブログ記事のリンクをチェックできます
Satinder sing

2
これは非常に役立ちました。URLを手動で設定すれば、任意の要素をドロップゾーンとして設定できます。成功ハンドラを使用して、プライマリフォームの非表示/無効なフィールドにファイル名を投稿しました。
DigitalDesignDj 2015年

40

私はまったく同じ問題を抱えていて、Varan Sinayeeの回答が元の質問を実際に解決した唯一のものであることがわかりました。しかし、その答えは単純化することができるので、これはより単純なバージョンです。

手順は次のとおりです。

  1. 通常のフォームを作成します(これはdropzoneで処理されなくなったため、メソッドとenctype引数を忘れないでください)。

  2. class="dropzone"(Dropzoneがそれにアタッチする方法で)divを内側に配置し、(id="yourDropzoneName"オプションの変更に使用)。

  3. Dropzoneのオプションを設定し、フォームとファイルが投稿されるURLを設定するには、autoProcessQueueを無効にし(ユーザーが「送信」を押した場合にのみ発生します)、複数のアップロードを許可します(必要な場合)。

  4. 送信ボタンがクリックされたときのデフォルトの動作の代わりにDropzoneを使用するようにinit関数を設定します。

  5. 引き続きinit関数内で、「sendingmultiple」イベントハンドラーを使用して、フォームデータをファイルとともに送信します。

ほら!$ _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());
        });
    }
}

1
このソリューションは適切で機能しますが、デフォルトの送信動作が妨げられるため、次のページにリダイレクトされません。
Felix G.

@TIIUNDER-ページのリロードなしでajax呼び出しを介してフォーム情報を送信するために準備された-それがe.preventDefault();がある理由です。
born2fr4g

1
@TIUNDER成功イベントでリダイレクトを追加できます
doflamingo 2017年

processQueue()電話の後にフォームを送信することはできますか?submit()またはを使用しようとしましたがclick()、どちらも機能しません。
グレイLi

1
+1これが唯一の有効な解決策のようです。formData.appendを1つずつ実行する代わりに、次のこともできます $(":input[name]", $("form")).each(function () { formData.append(this.name, $(':input[name=' + this.name + ']', $("form")).val()); }); (申し訳ありませんが、ここに改行を入れる方法がわかりません)
Aximili

20

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

2
投稿ありがとうございます!私の問題を解決しました。別の簡単な質問、これは(アップロードする)画像が選択されていない場合は機能しません、これを解決するにはどうすればよいですか?
佐藤

ところで、モデルバインディングでコントローラーアクションを使用し、このようなフォームを送信すると、モデルは空になります。何らかの理由で、このメソッドは実際のデータをモデルにバインドしません。
エドワードチョプリアン2016

1
autoProcessQueue = falseの場合、イベントは発生しません
cyril

@Satoの送信ボタンのクリックイベントで、galleryfile.getAcceptedFiles()。lengthを使用してドロップゾーンで受け入れられるファイルの長さを確認できます。ファイルがアップロードされていない場合は、フォームを送信する必要があります。
Varan Sinayee 2018

@EdwardChopuryanこれは、dropzoneでデータを送信する方法とは関係ありません。おそらく問題は、ASP.Net MVCなどのプラットフォーム上の入力タグの「命名規則」にあります。
Varan Sinayee 2018

11

Enyoのチュートリアルはすばらしい。

チュートリアルのサンプルスクリプトは、dropzoneに埋め込まれたボタン(つまり、フォーム要素)でうまく機能することがわかりました。ボタンをフォーム要素の外側に配置したい場合は、クリックイベントを使用してボタンを実現できました。

まず、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's the change from enyo's tutorial...

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

23
フォーム内にフォームを作成して送信することはできません。
ポール、

1
これを試してみると、dropzone-previewsコンテナが無視されているようです。Dropzoneはフォームの下部にプレビューを追加するだけです。'previewsContainer:' .dropzone-previews '、を構成に追加する必要があります。
アーロンヒル、

6
これは元の質問には答えません。元の質問は、アクションをトリガーするボタンの場所ではなく、既存のフォームでDropzoneを使用する方法でした。
CSSian、2015

7

sqramが言っていたことに加えて、Dropzoneにはドキュメント化されていない追加オプション "hiddenInputContainer"があります。このオプションを、隠しファイルフィールドを追加するフォームのセレクターに設定するだけです。そして出来上がり!Dropzoneが通常本文に追加する「.dz-hidden-input」ファイルフィールドは、魔法のようにフォームに移動します。Dropzoneソースコードを変更する必要はありません。

これでDropzoneファイルのフィールドがフォームに移動しますが、フィールドには名前がありません。だからあなたは追加する必要があります:

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

この行の後にdropzone.jsを追加します。

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

547行目あたり。


5

このための自動化ソリューションがあります。

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を無効にする必要はありません。通常のフォーム送信では、標準のフォームシリアル化を通じて、他のフォームフィールドを含むファイルを送信できます。

このメカニズムは、ファイルが処理されるときに、非表示の入力フィールドにbase64文字列としてファイルの内容を格納します。標準のbase64_decode()方法でPHPのバイナリ文字列にデコードできます。

この方法が大きなファイルで危険にさらされるかどうかはわかりませんが、最大40MBのファイルで機能します。


画像と一緒に送信される他のフィールドからのデータをどのようにデコードして処理しますか?
2018年

@sam他のフィールドをデコードする必要はありません。最初はエンコードされていません。ファイルのみがエンコードされています。
Umair Ahmed 2018

html、javascriptのサンプルコードと、laravel phpで取得する方法を共有できますか。
サム

1
複数の画像を追加する場合は、htmlファイルの入力を削除し、画像ごとにjsを追加する必要があります$( '#fileUpload')。append( '<input hidden name = "files []" value =' + content + ' /> ')contentはbase64でエンコードされた画像です。
AleXzpm

1
@codepushrは、有料ソリューションを検討していなかった当時の古い答えです。FileUploaderを購入しましたが、独自の悪意がありますが、ほとんど何でもできるようにカスタマイズできます。
Umair Ahmed

4

ドロップゾーンから「送信」イベントをキャッチすることでformDataを変更できます。

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

1
私はこの答えが好きですが、フィールド名と値が入力されていると想定しています。これは、フォームの送信とは別のときに発生する可能性があるアップロード時にトリガーされます。つまり、画像を送信するときにフォームに入力されているとは限りません。
アントニー

4

すべてのファイルを他のフォームデータと共に1つのリクエストで送信するために、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);
});

明らかに、これは実装の詳細に依存する回避策です。関連するソースコード


私は基本的にこのアプローチを使用しましたが、明らかな処理遅延のために、結局、myDropzone.on("thumbnail", () => {})イベントの下でファイルコンテンツ処理をフックしました。"addedFile"ファイルに対してすぐに処理を行うことは、まだundefinedアクセス中の可能性があります。
Matti

これを使用しようとしていますが、非表示のファイル入力フィールドをフォームに取り込むときに機能します。送信すると、投稿データにフィールドfiles[]が表示されますが、何をしても空白になります。何か案は?それが何か違いを生むなら、それをLaravelで行うこと。

こんにちは!選択したファイルがアップロードされるのはなぜですか。ファイルがドロップされた場合、ドロップされません(エラー4)。
Ingus

2

私も同じ問題に直面しているので、ここで回答を提供したいと思います。$ _ FILES要素を別のフォームと同じ投稿の一部として使用できるようにしたいと考えています。私の回答は@mrtnmgsに基づいていますが、その質問に追加されたコメントに注意しています。

まず、Dropzoneはajax経由でデータを投稿します

formData.appendオプションを使用するからといって、それでもUXアクションに取り組む必要があることを意味します。つまり、これはすべて舞台裏で行われ、典型的なフォームポストではありません。データがurlパラメーターに投稿されます。

次に、フォームの投稿を模倣したい場合は、投稿されたデータを保存する必要があります

これには$_POSTまたはを保存するサーバー側コードが必要です$_FILES、ユーザーがポストされたデータを受信したページに移動しないので、別のページのロード時にユーザーに利用可能なセッションでは。

3番目に、このデータが処理されるページにユーザーをリダイレクトする必要があります

データを投稿し、セッションに保存したので、追加のページでユーザーに表示/アクションする必要があります。ユーザーをそのページに送る必要もあります。

だから私の例では:

[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';
        })
    },
});

1

これは、既存のフォームでDropzone.jsを使用する方法のもう1つの例です。

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

これは#botofform、アップロード時にアップロードされたファイルの名前を使用できるように、id を持つdivがあることを前提としています。

注:アップロードスクリプトがtheuploadedfilename.jpeg dubblenoteを返したので、使用していないファイルがないかアップロードディレクトリをチェックし、それらを削除するクリーンアップスクリプトを作成する必要があります。


これは、他のフォームフィールドと一緒にドロップゾーン画像を送信しません。あなたがしていることは、画像を正常にアップロードし、画像名を保存してから、残りのフォームフィールドを画像名で再送信することです。

1

これが私のサンプルです。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>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.