web-dev-qa-db-ja.com

Dropzone.jsを使用した非JavaScript投稿

Dropzone.js( http://dropzonejs.com )をAJAXの代わりに標準のブラウザPOSTで動作させる方法があるかどうか疑問に思っています。

おそらく送信する直前に入力type = fileをDOMに挿入する方法はありますか?

18
MZAweb

いいえ。セキュリティ上の理由から、<input type='file'>の値を手動で設定することはできません。 Javascriptのドラッグアンドドロップ機能を使用すると、ファイル入力を完全に上回ります。ユーザーのコンピューターからファイルがフェッチされると、ファイルをサーバーに送信する唯一の方法はAJAXを使用することです。

回避策:代わりに、ファイルをシリアル化するか、文字列化してフォームに文字列として追加してから、サーバー側でシリアル化を解除することができます。

var base64Image;
var reader  = new FileReader();
reader.addEventListener("load", function () {
    base64Image = reader.result;
    // append the base64 encoded image to a form and submit
}, false);
reader.readAsDataURL(file);

おそらく、ファイル入力が醜くてスタイリングが難しいため、dropzone.jsを使用していますか?その場合は、この Dropzone.jsの代替 が有効な場合があります。フォームで送信できるカスタムスタイルの入力を作成できます。ドラッグアンドドロップもサポートしていますが、ドラッグアンドドロップを使用すると、フォームを希望どおりに送信できません。 免責事項:私は前述のライブラリの作成者です

将来の訪問者のために、私はこれをドロップゾーンオプションに追加しました:

addedfile: function (file) {
            var _this = this,
                    attachmentsInputContainer = $('#attachment_images');
            file.previewElement = Dropzone.createElement(this.options.previewTemplate);
            file.previewTemplate = file.previewElement;
            this.previewsContainer.appendChild(file.previewElement);
            file.previewElement.querySelector("[data-dz-name]").textContent = file.name;
            file.previewElement.querySelector("[data-dz-size]").innerHTML = this.filesize(file.size);
            if (this.options.addRemoveLinks) {
                file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\">" + this.options.dictRemoveFile + "</a>");
                file._removeLink.addEventListener("click", function (e) {
                    e.preventDefault();
                    e.stopPropagation();
                    if (file.status === Dropzone.UPLOADING) {
                        return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function () {
                            return _this.removeFile(file);
                        });
                    } else {
                        if (_this.options.dictRemoveFileConfirmation) {
                            return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function () {
                                return _this.removeFile(file);
                            });
                        } else {
                            return _this.removeFile(file);
                        }
                    }
                });
                file.previewElement.appendChild(file._removeLink);
            }
            attachmentsInputContainer.find('input').remove();
            attachmentsInputContainer.append(Dropzone.instances[0].hiddenFileInput).find('input').attr('name', 'files');
            return this._updateMaxFilesReachedClass();
        },

これは、dropzoneのaddedfileオプションのデフォルトの実装であり、3つの挿入があります。

宣言された変数attachmentsInputContainer。これは見えないブロックです。何かのようなもの

<div id="attachment_images" style="display:none;"></div>

ここでは、選択した画像とともに将来の入力を保存します。次に、関数の最後に、以前に追加した入力(存在する場合)をブロックから削除し、新しい入力を追加します

attachmentsInputContainer.find('input').remove();
attachmentsInputContainer.append(Dropzone.instances[0].hiddenFileInput).find('input').attr('name', 'files');

そして今、単純な送信ボタンを介してフォームを送信すると、input [name = "files"]値が送信されます。

まだ作成されていない可能性のあるファイルを投稿に追加するため、これをhackにしました

0
AlmasK89

これは私が過去のプロジェクトに使用したものです、

function makeDroppable(element, callback) {

var input = document.createElement('input');

input.setAttribute('type', 'file');

input.setAttribute('multiple', true);

input.style.display = 'none';

input.addEventListener('change', triggerCallback);

element.appendChild(input);

element.addEventListener('dragover', function(e) {

e.preventDefault();

e.stopPropagation();

element.classList.add('dragover');
});

element.addEventListener('dragleave', function(e) {

e.preventDefault();

e.stopPropagation();

element.classList.remove('dragover');
});

element.addEventListener('drop', function(e) {

e.preventDefault();

e.stopPropagation();

element.classList.remove('dragover');

triggerCallback(e);
});

element.addEventListener('click', function() {
input.value = null;
input.click();
});

function triggerCallback(e) {

  var files;

  if(e.dataTransfer) {

  files = e.dataTransfer.files;

} else if(e.target) {

  files = e.target.files;
}
callback.call(null, files);
}
}
0
BabyProgrammer

それで、私が正しく理解したなら、ドロップゾーンがアクティブになっているフォームを送信する前に、いくつかのデータ(input = file)を追加したいですよね?

もしそうなら、私はほとんど同じことをしなければならなかった、そして私はイベントを聞くことを通してそれを得た。 1つのファイルをアップロードするだけの場合は「送信」イベントをリッスンする必要がありますが、複数のアップロードを有効にする場合は「複数の送信」をリッスンする必要があります。これは、これを機能させるために使用したコードの一部です。

Dropzone.options.myAwesomeForm = {
  acceptedFiles: "image/*",
  autoProcessQueue: false,
  uploadMultiple: true,
  parallelUploads: 100,
  maxFiles: 100,

  init: function() {
    var myDropzone = this;

    [..some code..]

    this.on("sendingmultiple", function(files, xhr, formData) {
      var attaches = $("input[type=file]").filter(function (){
        return this.files.length > 0;
      });

      var numAttaches = attaches.length;

      if( numAttaches > 0 ) {
        for(var i = 0; i < numAttaches; i++){  
          formData.append(attaches[i].name, attaches[i].files[0]);
          $(attaches[i]).remove();
        }
      }
    });

    [..some more code..]

  }
}

以上です。お役に立てば幸いです:)

PS:文法の間違いがあったら申し訳ありませんが、英語は私の母国語ではありません

0
amandasantanati