ドロップファイルを標準のhtmlファイル入力にドラッグ


163

最近では、ファイルを特別なコンテナーにドラッグアンドドロップして、XHR 2でアップロードすることができます。ライブプログレスバーなど。ここに例があります。

しかし、それほどクールにしたくない場合もあります。私がしたいことは、ドラッグ&ドロップでファイルにある-一度に多くの- 標準のHTMLファイルの入力に<input type=file multiple>

それは可能ですか?ファイルドロップから正しいファイル名(?)でファイル入力を「埋める」方法はありますか?(フルファイルパスは、ファイルシステムのセキュリティ上の理由から使用できません。)

どうして?通常のフォームを提出したいので。すべてのブラウザとすべてのデバイス。ドラッグアンドドロップは、UXを拡張および簡素化するための段階的な拡張です。標準ファイル入力(+ multiple属性)を持つ標準フォームがそこにあります。HTML5拡張機能を追加したいのですが。

編集
私は知っているいくつかのことができますブラウザ時々ファイル入力自体にファイルをドロップ(ほとんど常に)。私はChromeが通常これを行うことを知っていますが、時々失敗して現在のページにファイルをロードします(フォームに入力している場合は大きな失敗)。私はそれをだまして、ブラウザで証明したいのです。


1
互換性にmac / safariを含める場合は、多少の痛みに備えてください。
Shark8

1
@ Shark8は、実際にはSafari / Macがすでにこれをサポートしている数少ないブラウザーの1つです。
Ricardo Tomasi

実際、どのブラウザもこれをサポートしていません。ファイル入力フィールドは(セキュリティのために)読み取り専用であり、それが問題です。バカなセキュリティ!
Rudie

2
することにより、この i「は-一度に多くの-標準のHTMLファイルの入力にドラッグ&ドロップファイル」を意味しました。
Ricardo Tomasi

3
複数のファイルをドラッグ/ドロップinput type="file" multipleしてSafariで正常に機能する
ロイド

回答:


71

以下はChromeとFFで動作しますが、IE10 +をカバーするソリューションもまだ見つけていません。

// dragover and dragenter events need to have 'preventDefault' called
// in order for the 'drop' event to register. 
// See: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#droptargets
dropContainer.ondragover = dropContainer.ondragenter = function(evt) {
  evt.preventDefault();
};

dropContainer.ondrop = function(evt) {
  // pretty simple -- but not for IE :(
  fileInput.files = evt.dataTransfer.files;

  // If you want to use some of the dropped files
  const dT = new DataTransfer();
  dT.items.add(evt.dataTransfer.files[0]);
  dT.items.add(evt.dataTransfer.files[3]);
  fileInput.files = dT.files;

  evt.preventDefault();
};
<!DOCTYPE html>
<html>
<body>
<div id="dropContainer" style="border:1px solid black;height:100px;">
   Drop Here
</div>
  Should update here:
  <input type="file" id="fileInput" />
</body>
</html>

おそらく、addEventListenerまたはjQuery(など)を使用してevtハンドラーを登録する必要があります。これは、簡潔にするためです。


3
わぁぁぁぁぁぁぁぁぁぁぁ!うまくいく!?それがまさに私が探していたものです。2年前は働いていませんでした。驚くばかり!もちろん、IEでは機能しません=)重要な質問:信頼性の高い機能検出はありますか?したがって、IEでドロップゾーンを非表示にできますが、機能しません。
Rudie

D'oh、少し遅れて:)現在、JSで単純なユーザーエージェントチェックを使用しています。もちろんMSIE Trident/(IE11)とEdge/(IE12)をテストする必要があります...
jlb

FF 48.0.2(Mac)は、「TypeError:ゲッターのみを持つプロパティの設定」を行にスローしますfileInput.files = evt.dataTransfer.files;。ただし、SafariとChromeはどちらも正常に動作します。
Risadinha 2016年

2
この例はLinuxのfirefox 45では動作しませんが、Chromeでは動作します。コンソールエラーは発生しません。ファイルがドロップされたことを示すだけではありません。
ブライアンオークリー2017

1
実際、私は解決策を見つけようとする投稿をしましたが、自分で考え出しました。かなり単純な変更、fileInputs [index] = ...ファイルデータを特定の入力に渡し、関数showNextを呼び出して新しい入力を追加するstackoverflow.com/a/43397640/6392779
nick

51

私はこれに対する解決策を作りました。

このメソッドのドラッグアンドドロップ機能は、Chrome、Firefox、Safariでのみ機能します。(IE10で動作するかどうかはわかりません)が、他のブラウザーでは、[またはここをクリック]ボタンは正常に動作します。

エリアにファイルをドラッグするとき、入力フィールドは単にマウスに追従し、ボタンも追加しました。

不透明度0のコメントを外します。ファイル入力は表示されているだけなので、何が起こっているかを確認できます。


そのため、ボタンも追加しました^^しかし、そうです。私はそれを使いません...それとも私は!?
BjarkeCK

それがどのように機能するのかを知っていればいいのですが...すべてのドラッグ/ドロップ機能がホバー効果の追加に対処しなければならないようです...しかし、本当にわかりません。ルックスフィドルで良いが、私は、Internet Explorerをサポートする必要があるため、私はそれを使用することができるとは思わない
nmz787

1
@PiotrKowalski呼び出しスタックがオーバーフローするまで、再帰呼び出しがトリガーされる可能性があると思います
John

2
私はそのスタイルだけを使用してしまいました。入力を100%の幅と高さにすると、移動するよりもうまくいきます。
エディ

2
マウスポインターでホバリングを続ける「ファイルが選択されていません」を取り除く方法はありますか?@BjarkeCK
Abhishek Singh

27

これは「DTHML」HTML5の方法です。通常のフォーム入力(これはRicardo Tomasiが指摘したように読み取り専用です)。次に、ファイルがドラッグされると、フォームに添付されます。この方法でアップロードされたファイルを受け入れるには、アクションページを変更する必要があります。

function readfiles(files) {
  for (var i = 0; i < files.length; i++) {
    document.getElementById('fileDragName').value = files[i].name
    document.getElementById('fileDragSize').value = files[i].size
    document.getElementById('fileDragType').value = files[i].type
    reader = new FileReader();
    reader.onload = function(event) {
      document.getElementById('fileDragData').value = event.target.result;}
    reader.readAsDataURL(files[i]);
  }
}
var holder = document.getElementById('holder');
holder.ondragover = function () { this.className = 'hover'; return false; };
holder.ondragend = function () { this.className = ''; return false; };
holder.ondrop = function (e) {
  this.className = '';
  e.preventDefault();
  readfiles(e.dataTransfer.files);
}
#holder.hover { border: 10px dashed #0c0 !important; }
<form method="post" action="http://example.com/">
  <input type="file"><input id="fileDragName"><input id="fileDragSize"><input id="fileDragType"><input id="fileDragData">
  <div id="holder" style="width:200px; height:200px; border: 10px dashed #ccc"></div>
</form>

ウィンドウ全体をドロップゾーンにできると、さらに上司になります。Gmailのように、ウィンドウに出入りするHTML5ドラッグイベントを検出するにどうすればよいですか?を参照してください。


1
IE 9以下はHTML5ファイルをサポートしないため、良い解決策はIE <10では機能しませんAPI :(
Develoger

1
この行:document.getElementById( 'fileDragData')。value = files [i] .slice(); reader.onload関数で置き換えられているため、必要ありません
kurdtpage

ファイルのアップロードを必要としない、別のかわいいドラッグアンドドロップアプリケーションを次に示します。誰かがもっと勉強したい場合に備えてリンクする。codepen.io/anon/pen/MOPvZK?editors=1010
William Entriken 2017年

1
IE 10のソリューションは低下し、次のもののみを表示することですinput type=file
William Entriken 2017年

何かが足りないのですか、それとも.value、foreループを繰り返すたびに、常に最新のファイルでプロパティを上書きしていますか?
ケビン・バーク

13

//----------App.js---------------------//
$(document).ready(function() {
    var holder = document.getElementById('holder');
    holder.ondragover = function () { this.className = 'hover'; return false; };
    holder.ondrop = function (e) {
      this.className = 'hidden';
      e.preventDefault();
      var file = e.dataTransfer.files[0];
      var reader = new FileReader();
      reader.onload = function (event) {
          document.getElementById('image_droped').className='visible'
          $('#image_droped').attr('src', event.target.result);
      }
      reader.readAsDataURL(file);
    };
});
.holder_default {
    width:500px; 
    height:150px; 
    border: 3px dashed #ccc;
}

#holder.hover { 
    width:400px; 
    height:150px; 
    border: 3px dashed #0c0 !important; 
}

.hidden {
    visibility: hidden;
}

.visible {
    visibility: visible;
}
<!DOCTYPE html>

<html>
    <head>
        <title> HTML 5 </title>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.js"></script>
    </head>
    <body>
      <form method="post" action="http://example.com/">
        <div id="holder" style="" id="holder" class="holder_default">
          <img src="" id="image_droped" width="200" style="border: 3px dashed #7A97FC;" class=" hidden"/>
        </div>
      </form>
    </body>
</html>


2
ユーザーには何が表示されますか?フィドルやオンラインの例を作れますか?
ルディー、2014

@Rudie実行コードスニペットをクリックし、1つの画像をドラッグアンドドロップして表示してください。ドロップされた画像のプレビューが表示されます。
Dipak 2017

6

理論的には、をオーバーレイする要素を追加し、そのイベントを<input/>使用してdrop(File APIを使用して)ファイルをキャプチャし、それらを入力に渡すことができますfiles配列に。

ファイル入力が読み取り専用であることを除いてです。これは古い問題です。

ただし、フォームコントロールを完全にバイパスし、XHRを介してアップロードすることはできます(そのサポートについては不明です)。

また、周辺領域の要素を使用して、Chromeのドロップイベントをキャンセルし、ファイルをロードするデフォルトの動作を防止することもできます。

入力に複数のファイルをドロップすると、SafariとFirefoxですでに機能します。


6
私が質問で言ったように:私はXHR2を知っており、それを使用したくありません。「ファイル入力は読み取り専用です」という重要な部分を私は推測します。残念です...ドロップイベントをキャンセルすることは悪くありません。私が望んだほど良くはありませんが、おそらく最高です。Chromeでは複数のファイルをドロップすることもできます。Chromeでは、ディレクトリのアップロードもできるようになりました。すべて非常にkewlで私のケースを助けていません=(
Rudie

5

これが私が思いついたものです。

JqueryとHtmlを使用します。これにより、挿入ファイルに追加されます。

var dropzone = $('#dropzone')


dropzone.on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
    e.preventDefault();
    e.stopPropagation();
  })

dropzone.on('dragover dragenter', function() {
    $(this).addClass('is-dragover');
  })
dropzone.on('dragleave dragend drop', function() {
    $(this).removeClass('is-dragover');
  })  
  
dropzone.on('drop',function(e) {
	var files = e.originalEvent.dataTransfer.files;
	// Now select your file upload field 
	// $('input_field_file').prop('files',files)
  });
input {	margin: 15px 10px !important;}

.dropzone {
	padding: 50px;
	border: 2px dashed #060;
}

.dropzone.is-dragover {
  background-color: #e6ecef;
}

.dragover {
	bg-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="" draggable='true' style='padding: 20px'>
	<div id='dropzone' class='dropzone'>
		Drop Your File Here
	</div>
	</div>


4

CSSのみのソリューションの場合:

<div class="file-area">
    <input type="file">
    <div class="file-dummy">
        <span class="default">Click to select a file, or drag it here</span>
        <span class="success">Great, your file is selected</span>
    </div>
</div>

.file-area {
    width: 100%;
    position: relative;
    font-size: 18px;
}
.file-area input[type=file] {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    opacity: 0;
    cursor: pointer;
}
.file-area .file-dummy {
    width: 100%;
    padding: 50px 30px;
    border: 2px dashed #ccc;
    background-color: #fff;
    text-align: center;
    transition: background 0.3s ease-in-out;
}
.file-area .file-dummy .success {
    display: none;
}
.file-area:hover .file-dummy {
    border: 2px dashed #1abc9c;
}
.file-area input[type=file]:valid + .file-dummy {
    border-color: #1abc9c;
}
.file-area input[type=file]:valid + .file-dummy .success {
    display: inline-block;
}
.file-area input[type=file]:valid + .file-dummy .default {
    display: none;
}

https://codepen.io/Scribblerockerz/pen/qdWzJwから変更


4

Chromeでいくつかのトリックが機能することを知っています。

ファイルをドロップゾーンにドロップdataTransfer.filesすると、FileListドラッグしたすべてのファイルを含むオブジェクト(オブジェクトの一種)が表示されます。一方、<input type="file" />要素にはfiles同じプロパティがあります。FileListタイプのオブジェクトでます。

したがって、dataTransfer.filesオブジェクトをinput.filesプロパティに割り当てるだけです。


3
はい、それは最近です。トリックではありません。非常に意図的です。また、非常に意図的に非常に制限されています。リストにファイルを追加したり、リストを変更したりすることはできません。ドラッグアンドドロップではファイルを覚えて追加できますが、追加することはinput.filesできません=(
Rudie

3

2018年にこれを行うことを検討している人のために、私はここに投稿されているすべての古いものよりもはるかに優れたシンプルなソリューションを用意しています。バニラHTML、JavaScript、CSSだけで、見栄えの良いドラッグ&ドロップボックスを作成できます。

(これまでのところChromeでのみ機能します)

HTMLから始めましょう。

<div>
<input type="file" name="file" id="file" class="file">
<span id="value"></span>
</div>

次に、スタイリングについて説明します。

    .file {
        width: 400px;
        height: 50px;
        background: #171717;
        padding: 4px;
        border: 1px dashed #333;
        position: relative;
        cursor: pointer;
    }

    .file::before {
        content: '';
        position: absolute;
        background: #171717;
        font-size: 20px;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 100%;
        height: 100%;
    }

    .file::after {
        content: 'Drag & Drop';
        position: absolute;
        color: #808080;
        font-size: 20px;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }

これを実行した後は、既に問題ありません。しかし、実際にアップロードしたファイルを見たいと思っているので、JavaScriptを実行します。そのpfp値のスパンを覚えていますか?ここでファイル名を出力します。

let file = document.getElementById('file');
file.addEventListener('change', function() {
    if(file && file.value) {
        let val = file.files[0].name;
        document.getElementById('value').innerHTML = "Selected" + val;
    }
});

以上です。


Uncaught TypeErrorが発生する:このコードを使用すると、nullのプロパティ「addEventListener」を読み取ることができません-Chromeの場合-最新バージョンのChromeでは機能しませんか?
火で火を

Chromeの最新バージョンでは、問題なく動作します。正しいIDを使用していることを確認してください
Michael

1

@BjarkeCKによる素晴らしい作品。私は彼の作品にいくつかの変更を加え、jqueryのメソッドとして使用しました。

$.fn.dropZone = function() {
  var buttonId = "clickHere";
  var mouseOverClass = "mouse-over";

  var dropZone = this[0];
  var $dropZone = $(dropZone);
  var ooleft = $dropZone.offset().left;
  var ooright = $dropZone.outerWidth() + ooleft;
  var ootop = $dropZone.offset().top;
  var oobottom = $dropZone.outerHeight() + ootop;
  var inputFile = $dropZone.find("input[type='file']");
  dropZone.addEventListener("dragleave", function() {
    this.classList.remove(mouseOverClass);
  });
  dropZone.addEventListener("dragover", function(e) {
    console.dir(e);
    e.preventDefault();
    e.stopPropagation();
    this.classList.add(mouseOverClass);
    var x = e.pageX;
    var y = e.pageY;

    if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) {
      inputFile.offset({
        top: y - 15,
        left: x - 100
      });
    } else {
      inputFile.offset({
        top: -400,
        left: -400
      });
    }

  }, true);
  dropZone.addEventListener("drop", function(e) {
    this.classList.remove(mouseOverClass);
  }, true);
}

$('#drop-zone').dropZone();

フィドル


1
参考:フィドルリンクが壊れています。
jimiayler 2018

1

数年後、私はこのライブラリを構築しましたファイルを任意のHTML要素にドロップするためにを。

こんな風に使えます

const Droppable = require('droppable');

const droppable = new Droppable({
    element: document.querySelector('#my-droppable-element')
})

droppable.onFilesDropped((files) => {
    console.log('Files were dropped:', files);
});

// Clean up when you're done!
droppable.destroy();

後でフォームを送信するときに、選択したファイルをどのようにフェッチしますか?
Nikhil VJ

-1

あなたができることは、ファイル入力を表示し、それを透明なドロップ領域でオーバーレイすることfile[1]です。{ enctype="multipart/form-data"FORMタグ内に必ず入れてください。}

次に、ドロップエリアに、ファイル2..number_of_filesのファイル入力を動的に作成して追加のファイルを処理させます。必ず、同じベース名を使用し、値属性を適切に入力してください。

最後に(フロントエンド)フォームを送信します。


このメソッドを処理するために必要なのは、ファイルの配列を処理するようにプロシージャを変更することだけです。


1
multiple最近のファイル入力には属性があります。複数のファイルを入力する必要はありません。それは問題ではありません。Fileオブジェクトをファイル入力に取り込むにはどうすればよいですか?これにはいくつかのコード例が必要だと思います...
Rudie

1
@Rudieはできません、それが問題です。
Ricardo Tomasi

1
何ができないの?複数?はい、できます。私はちょうどそれを言った。倍数は問題ではありません。(ドラッグされた)Fileオブジェクトからファイル入力にファイルを取得することは問題です。
Rudie

@Rudieがドラッグされたファイルをファイル入力に取得することは、Chrome / FF(filesプロパティを使用)で可能ですが、IEで管理していません-運がよかったですか?
jlb

1
@jlb「filesプロパティを使用する」とはどういう意味ですか?関連するコードで答えてもらえますか?私が探していたものは、どのブラウザでも機能しません/存在しません。
ルディー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.