ドラッグアンドドロップでファイルをアップロードができ、画像の場合はプレビューも見れるJS

```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ドラッグアンドドロップでファイルアップロード</title>
    <style></style>
  </head>
  <body>
    <style>
      .js-fileUpload {
        border: 1px dashed #9b9b9b;
        border-radius: 10px;
        padding: 42px;
        text-align: center;
      }

      .text {
        margin-bottom: 10px;
      }

      .file-name {
        margin-top: 10px;
      }

      .is-hidden {
        display: none !important;
      }

      .file-preview {
        display: flex;
        justify-content: center;
        margin: 20px auto 10px;
      }

      .file-preview img {
        max-height: 400px;
        object-fit: contain;
      }

      .upload-button {
        background-color: #333;
        border-radius: 5px;
        color: #fff;
        padding: 5px 10px;
        width: 150px;
      }

      .cancel-button {
        border: 1px solid #333;
        border-radius: 5px;
        margin: 10px auto 0;
        padding: 5px 10px;
        width: 150px;
      }
    </style>
    <div class="js-fileUpload">
      <div class="text">ここにファイルをドラッグ＆ドロップ</div>
      <input type="file" class="file-input is-hidden" multiple />
      <button class="upload-button">ファイル選択</button>
      <div class="file-preview is-hidden"></div>
      <div class="file-name is-hidden"></div>
      <div class="cancel-button is-hidden">キャンセル</div>
    </div>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        const fileUpload = document.querySelector(".js-fileUpload");

        if (fileUpload) {
          const text = fileUpload.querySelector(".text");
          const fileInput = fileUpload.querySelector(".file-input");
          const uploadButton = fileUpload.querySelector(".upload-button");
          const cancelButton = fileUpload.querySelector(".cancel-button");
          const fileName = fileUpload.querySelector(".file-name");
          const preview = fileUpload.querySelector(".file-preview");

          fileUpload.addEventListener("dragover", (event) => {
            event.preventDefault();
            fileUpload.style.borderColor = "#666";
          });

          fileUpload.addEventListener("mouseover", (event) => {
            event.preventDefault();
            fileUpload.style.borderColor = "#666";
          });

          fileUpload.addEventListener("dragleave", (event) => {
            event.preventDefault();
            fileUpload.style.borderColor = "";
          });

          fileUpload.addEventListener("mouseout", (event) => {
            event.preventDefault();
            fileUpload.style.borderColor = "";
          });

          fileUpload.addEventListener("drop", (event) => {
            event.preventDefault();
            fileUpload.style.borderColor = "";
            const files = event.dataTransfer.files;
            if (files.length > 0) {
              // 新しいDataTransferオブジェクトを作成し、ドロップされたファイルを設定
              const dataTransfer = new DataTransfer();
              for (let i = 0; i < files.length; i++) {
                dataTransfer.items.add(files[i]);
              }
              fileInput.files = dataTransfer.files;
              handleFiles(files);
              fileInput.dispatchEvent(new Event("change")); // changeイベントを手動でトリガー
            }
          });

          uploadButton.addEventListener("click", () => {
            if (fileInput.files.length > 0) {
              alert("ファイルをアップロードしました。");
            } else {
              fileInput.click();
            }
          });

          fileInput.addEventListener("change", () => {
            if (fileInput.files.length > 0) {
              handleFiles(fileInput.files);
            }
          });

          cancelButton.addEventListener("click", () => {
            fileInput.value = "";
            fileName.textContent = "";
            preview.innerHTML = "";
            uploadButton.textContent = "ファイル選択";
            text.classList.remove("is-hidden");
            preview.classList.add("is-hidden");
            cancelButton.classList.add("is-hidden");
          });

          function handleFiles(files) {
            if (files.length > 0) {
              fileName.classList.remove("is-hidden");
              fileName.textContent = Array.from(files)
                .map((file) => file.name)
                .join(", ");

              text.classList.add("is-hidden");
              uploadButton.textContent = "選択したファイルをアップロードする";
              preview.innerHTML = "";
              preview.classList.remove("is-hidden");

              Array.from(files).forEach((file) => {
                if (file.type.startsWith("image/")) {
                  const reader = new FileReader();
                  reader.onload = (e) => {
                    const img = document.createElement("img");
                    img.src = e.target.result;
                    preview.appendChild(img);
                  };
                  reader.readAsDataURL(file);
                }
              });
            }
            fileName.classList.add("is-hidden");
            cancelButton.classList.remove("is-hidden");
          }
        }
      });
    </script>
  </body>
</html>


```