WEB制作、マーケティングに関する情報をお届けします。ホームページ制作会社、テラのブログ

ドラッグ&ドロップでファイルをアップ、サムネイルも表示する方法

タグ:

ブラウザがデフォルトで用意している入力フォーマットではファイルアップロード時にはファイル名のみが表示されます。ユーザーに対しては画像のプレビューを表示させた方が親切と言えるでしょう。
尚且つドラッグ&ドロップでファイルを追加できると、とても便利です。
今回は『ドラッグ&ドロップでファイルをアップ、サムネイルも表示する方法』を紹介します。

コードを紹介

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ファイルアップロード</title>
    <style>
        /* ドロップゾーンのスタイル */
        #drop_zone {
            width: 100%;
            height: 150px;
            border: 2px dashed #ccc;
            border-radius: 10px;
            text-align: center;
            line-height: 150px;
            font-size: 16px;
            color: #999;
            margin-bottom: 20px;
            cursor: pointer; /* クリック可能に見せるために追加 */
        }

        /* サムネイル表示エリアのスタイル */
        #thumbnail {
            display: flex;
            flex-wrap: wrap;
        }
        .thumbnail-item {
            margin-right: 10px;
            margin-bottom: 10px;
            text-align: center;
        }
        .thumbnail-item img {
            max-width: 100px;
            max-height: 100px;
        }
        .thumbnail-item p {
            font-size: 14px;
        }

        /* ファイル入力のスタイルを隠す */
        input[type="file"] {
            display: none;
        }
    </style>
</head>
<body>

<h2>ファイルをドラッグ&ドロップ、またはクリックして挿入</h2>

<!-- ドロップゾーン&クリックゾーン -->
<div id="drop_zone">ここにファイルをドラッグ&ドロップ、またはクリックしてください</div>
<input type="file" id="file_input" multiple accept=".jpg, .jpeg, .png, .pdf">

<!-- サムネイルを表示するエリア -->
<div id="thumbnail"></div>

<!-- サムネイル表示用のJavaScript -->
<script>
    // 対応ファイルタイプ
    const validFileTypes = ['image/jpeg', 'image/png', 'application/pdf'];

    // ドロップゾーンに関するイベント設定
    const dropZone = document.getElementById('drop_zone');
    const fileInput = document.getElementById('file_input');

    // クリック時にファイル選択ダイアログを表示
    dropZone.addEventListener('click', function() {
        fileInput.click();  // ファイル選択ダイアログを開く
    });

    // ファイルが選択された場合の処理
    fileInput.addEventListener('change', function() {
        const files = fileInput.files;
        handleFiles(files);  // ファイルの処理
    });

    // ドロップされたときの処理
    dropZone.addEventListener('dragover', function(event) {
        event.preventDefault();
        dropZone.style.borderColor = '#000';  // ドラッグ中のスタイル変更
    });

    dropZone.addEventListener('dragleave', function() {
        dropZone.style.borderColor = '#ccc';  // 元に戻す
    });

    dropZone.addEventListener('drop', function(event) {
        event.preventDefault();
        dropZone.style.borderColor = '#ccc';  // 元に戻す

        const files = event.dataTransfer.files;
        handleFiles(files);  // ファイルの処理
    });

    // ファイル処理関数
    function handleFiles(files) {
        const thumbnailDiv = document.getElementById('thumbnail');
        thumbnailDiv.innerHTML = '';  // サムネイルエリアをクリア

        Array.from(files).forEach(file => {
            // 対応ファイルかどうかのチェック
            if (!validFileTypes.includes(file.type)) {
                alert('対応していないファイル形式です。PDF, JPG, PNG のみです。');
                return;
            }

            const reader = new FileReader();
            const div = document.createElement('div');
            div.classList.add('thumbnail-item');

            reader.onload = function(event) {
                // 画像の場合はプレビューを表示
                if (file.type.startsWith('image/')) {
                    const img = document.createElement('img');
                    img.src = event.target.result;
                    div.appendChild(img);
                }
                // PDFの場合はサムネイルとしてPDFアイコンを表示
                else if (file.type === 'application/pdf') {
                    const img = document.createElement('img');
                    img.src = 'https://upload.wikimedia.org/wikipedia/commons/8/87/PDF_file_icon.svg';  // PDFアイコンを使用
                    div.appendChild(img);
                }
                // ファイル名を表示
                const p = document.createElement('p');
                p.textContent = file.name;
                div.appendChild(p);

                thumbnailDiv.appendChild(div);
            };

            // ファイル読み込み
            reader.readAsDataURL(file);
        });
    }
</script>

</body>
</html>

コードを解説

HTMLを解説

ドラッグ&ドロップするエリアを作成します。
javascriptで操作するためにID名を振っておきます。

<div id="drop_zone">ここにファイルをドラッグ&ドロップ、またはクリックしてください</div>

入力項目の作成、こちらもjavascriptで操作するためにID名を振っておきます。

<input type="file" id="file_input" multiple accept=".jpg, .jpeg, .png, .pdf">

サムネイルを表示するエリアを作成します。
こちらもID名を振っておきます。

<div id="thumbnail"></div>

CSSの解説

ドラッグ&ドロップする場所のCSSを設定します。

#drop_zone {
    width: 100%;
    height: 150px;
    border: 2px dashed #ccc;
    border-radius: 10px;
    text-align: center;
    line-height: 150px;
    font-size: 16px;
    color: #999;
    margin-bottom: 20px;
    cursor: pointer; /* クリック可能に見せるために追加 */
}

サムネイルを表示するためCSSを設定します。
『.thumbnail-item』はjavascriptで生成した要素に対してのCSSです。

#thumbnail {
    display: flex;
    flex-wrap: wrap;
}
.thumbnail-item {
    margin-right: 10px;
    margin-bottom: 10px;
    text-align: center;
}
.thumbnail-item img {
    max-width: 100px;
    max-height: 100px;
}
.thumbnail-item p {
    font-size: 14px;
}

デフォルトの入力項目は非表示に設定します。

input[type="file"] {
    display: none;
}

javascriptを解説

対応するファイルを指定します。

const validFileTypes = ['image/jpeg', 'image/png', 'application/pdf'];

ドラッグ&ドロップ時の処理を設定します。

dragoverはドラッグオーバー時に実行されます。
以下では、『event.preventDefault();』でデフォルトイベントのキャンセル、『dropZone.style.borderColor = ‘#000’;』でID名『drop_zone』にCSSのボーダーカラーを設定しています。

addEventListener('dragover', function(event) {
    event.preventDefault();
    dropZone.style.borderColor = '#000'
});

dragleaveでドラッグが外れた時の処理を記載していきます。
以下では『dropZone.style.borderColor = ‘#ccc’;』でID名『drop_zone』に元から定義していたCSSを設定しています。

dropZone.addEventListener('dragleave', function() {
    dropZone.style.borderColor = '#ccc';
});

dropで対象にファイルがドロップされた時に実行されます。
以下ではデフォルトベントのキャンセル、でID名『drop_zone』に元から設定していたCSSを定義しています。
『const files = event.dataTransfer.files;』はドロップの際にのみ動作し、ファイルのデータを取得できます。
『handleFiles(files);』でファイルを処理する関数へと値を引き渡します。

dropZone.addEventListener('drop', function(event) {
    event.preventDefault();
    dropZone.style.borderColor = '#ccc'

    const files = event.dataTransfer.files;
    handleFiles(files);
});

以下でファイルを処理する関数を作成していきます。

function handleFiles(files) {
}

サムネイルを表示するIDを取得します。
ファイルドロップ時に毎回、初期化するために空値を代入します。

const thumbnailDiv = document.getElementById('thumbnail');
thumbnailDiv.innerHTML = '';

複数のファイルを一気にアップロードする場合にループをかけます。

Array.from(files).forEach(file => {
});

以下で対応するファイルをチェック対応していないファイルがアップロードされた場合にアラートを出します。
『return』で処理を停止します。

if (!validFileTypes.includes(file.type)) {
    alert('対応していないファイル形式です。PDF, JPG, PNG のみです。');
    return;
}

『new FileReader()』ではドラッグ&ドロップしたファイルをアクセス、読み取りを行います。
『document.createElement(‘div’)』でdivタグを生成、『div.classList.add(‘thumbnail-item’);』でクラス名を付与します。

const reader = new FileReader();
const div = document.createElement('div');
div.classList.add('thumbnail-item');

以下でファイルの処理を行います。

reader.onload = function(event) {
};

『if (file.type.startsWith(‘image/’)) {}』で画像の場合の処理を行います。
imgタグの生成、『img.src = event.target.result;』でimgタグのsrc属性にURLを設定、javascriptで作成したクラス名『thumbnail-item』の子要素にimgタグを出力します。

document.createElement('img');
img.src = event.target.result;
div.appendChild(img);

『else if (file.type === ‘application/pdf’) {}』でPDFの場合の処理を行います。
『document.createElement(‘img’)』でimgタグの生成、『img.src = ‘https://upload.wikimedia.org/wikipedia/commons/8/87/PDF_file_icon.svg’;』でPDFアイコンを表示させています。wikipediaから直接取得していますがURLを任意のものに変更可能です。

else if (file.type === 'application/pdf') {
                const img = document.createElement('img');
                img.src = 'https://upload.wikimedia.org/wikipedia/commons/8/87/PDF_file_icon.svg';  // PDFアイコンを使用
                div.appendChild(img);
            }

pタグを生成、『p.textContent』でファイル名を代入、pタグを出力しています。

const p = document.createElement('p');
p.textContent = file.name;
div.appendChild(p);

ID名『thumbnail』の子要素に出力します。

thumbnailDiv.appendChild(div);

以下では非同期でファイルを読み込んでくれます。

reader.readAsDataURL(file);

まとめ

以上、『ドラッグ&ドロップでファイルをアップ、サムネイルも表示する方法』でした。
少し面倒ではありますがユーザビリティを向上させる一つの手段ではありますのでクライアントから要望があった場合はぜひ、ご参考ください。

テラ合同会社(東京都)

テラは2014年に東京都でスタートアップしたホームページ制作会社です。ホームページ制作以外にも広告運用、マーケティング、ブランディング、印刷物など幅広い領域をサポートしています。
コーポレートサイトはこちらをご覧ください。