いつも何気なく行うファイルのドラッグアンドドロップ。
どのような仕組みで動いているのか、どんなデータが受け渡しされているのか
サンプルアプリを作成して試してみました。
本記事はwindowsで動作確認を行っています。
ブラウザでファイル受け取り
ファイルのアップロード機能とよく一緒に用意されるドラッグアンドドロップ。シンプルなhtmlファイルをjsファイルを用意して、どのようなデータを受け取っているのか表示できるようにしました。
index.html
単なるdivで枠を用意しました。テキストエリアは、ドロップしたファイルの情報を表示する場所です。
<div
id="drop-area"
style="
width: 300px;
height: 200px;
border: 2px dashed gray;
text-align: center;
line-height: 200px;
"
>
ここにドラッグ&ドロップ
</div>
<h3>ファイルの内容</h3>
<textarea id="log-area" rows="10" cols="50" readonly></textarea>
<script src="index.js"></script>
index.js
dropイベントでファイルを受け取り、中身を表示します。
const logArea = document.getElementById("log-area");
function log(message) {
logArea.value += message + "\n";
}
function logClear() {
logArea.value = "";
}
const dropArea = document.getElementById("drop-area");
// ファイルをドラッグしてきた
dropArea.addEventListener("dragover", (event) => {
event.preventDefault();
dropArea.style.backgroundColor = "lightcyan";
});
// ドラッグしながら出ていった
dropArea.addEventListener("dragleave", () => {
dropArea.style.backgroundColor = "white";
});
// ファイルドロップ
dropArea.addEventListener("drop", (event) => {
event.preventDefault();
// ドロップしたら色を戻す
dropArea.style.backgroundColor = "white";
const dataTransfer = event.dataTransfer;
// 読み取れなかったら終了
if (!dataTransfer) return;
// 初期化
logClear();
for (const type of dataTransfer.types) {
log(`タイプ: ${type}`);
}
if (dataTransfer.files.length > 0) {
log("ドロップされたファイル:");
Array.from(dataTransfer.files).forEach((file) => {
const reader = new FileReader();
reader.onload = () => {
log(`名前: ${file.name}`);
log(` - MIMEタイプ: ${file.type}`);
log(` - サイズ: ${file.size} bytes`);
log(`中身:\n${reader.result}`);
};
reader.onerror = () => {
log("読み込みエラー:", reader.error);
};
reader.readAsText(file);
});
}
});
dataTransferを利用してドロップされたデータの情報を取得します。
const dataTransfer = event.dataTransfer;
複数ファイルの受け渡しにも対応しているためforEachで取り出しています。
Array.from(dataTransfer.files).forEach((file) => {
// ファイルごとに処理
それぞれ、ファイル名、MIMEタイプ、ファイルサイズを取得することができます。
log(`名前: ${file.name}`);
log(` - MIMEタイプ: ${file.type}`);
log(` - サイズ: ${file.size} bytes`);
MIMEタイプはファイルの種類をタイプ/サブタイプの形式で表したものです。例えば、png画像の場合image/pngとなります。
ファイルの内容自体を取得するには別途FileReaderを用意して、読み込みます。
const reader = new FileReader();
reader.onload = () => {
// ファイル読み込み完了したら表示
log(`中身:\n${reader.result}`);
};
reader.onerror = () => {
log("読み込みエラー:", reader.error);
};
// テキスト形式で読み込み
reader.readAsText(file);
テキストエリアに内容を表示するために文字列が取得できるreadAsTextを使用しています。
動作確認
index.htmlをブラウザで表示して動作確認します。VScodeのデバッグ実行を利用しました。
windowsのエクスプローラーより、適当なファイルをドラッグアンドドロップします。
テキストエリアにファイルの内容が表示されます。
タイプ: Files
ドロップされたファイル:
名前: image.png
- MIMEタイプ: image/png
- サイズ: 23878 bytes
中身:
�PNG
...(以下略)
中身については、バイナリデータである画像ファイルを無理やり文字列として表示しているため、文字化けしまくっています。
他にもファイルをドロップしてみます。
タイプ: Files
ドロップされたファイル:
名前: index.js
- MIMEタイプ: text/javascript
- サイズ: 1598 bytes
中身:
const logArea = document.getElementById("log-area");
function log(message) {
logArea.value += message + "\n";
}...(以下略)
テキスト形式のファイルは、読める形でファイルの中身が取得できました。
Windows Formアプリでファイル送り出し
ドラッグアンドドロップのドラッグ元、エクスプローラーからファイルをドラッグすることがほとんどです。Windows Formアプリを作成してファイルのドラッグできるようにしてみます。
画面レイアウト
Visual Studioより、.NETのフォームアプリを作成します。
適当にラベルを設置します。
ラベルに対し、プロパティよりMouseDownのイベントを作成します。
MainForm.cs
MouseDownのイベントを実装します。
namespace FileDragDemo
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void Label_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// ファイルパス
string[] files = { @"D:\image.png" };
// FileDrop として設定
DataObject data = new DataObject(DataFormats.FileDrop, files);
// ドラッグ開始
DoDragDrop(data, DragDropEffects.Copy);
}
}
}
}
これだけです。
簡単のために、ドラッグさせるファイルは固定、フルパスで指定しています。
DataObjectを作成し、ドラッグ開始時に渡します。
内部的には、OLE (Object Linking and Embedding) Drag and Dropと呼ばれる、Windowsに組み込まれているシステムを使って、ファイルをやりとりしています。
動作確認
Formアプリをデバッグ実行して、ドラッグできるか確認します。
ラベルをドラッグしようとすると、マウスの形状が🚫に変わります。
さらにフォームの外側までドラッグすると、なにか持っていそうな形状になりました。

エクスプローラーからファイルをドラッグしたときのように、ファイルのアイコン表示することも検討しましたが諦めました。
Formからhtmlにドラッグアンドドロップ
作成したFormアプリから、作成したhtmlに対してファイルをドラッグアンドドロップしてみます。
ドラッグアンドドロップでファイルを渡すことができました。
まとめ
日常的な操作であるファイルのドラッグ&ドロップが、ブラウザとWindows Formアプリ間でどのように実現されているかを、サンプルコードを通して解説しました。
ブラウザ側の実装(ドロップ先)
- drop イベントで処理開始
- イベントオブジェクトの dataTransfer を通じて取得
Windows Form側の実装(ドラッグ元)
- DataObject を作成し、ファイルパスの情報を DataFormats.FileDrop 形式で格納
- ドラッグ操作は DoDragDrop() メソッドで実行
ドラッグ&ドロップを実装するときに、参考にしてみてください。





