marcelh
marcelh

Reputation: 41

File picker causes Chrome to freeze up

I have built a component that lets a user upload a file by either clicking on it, or dropping a file directly on it. Most of the time this works just fine, but I have noticed that it causes Google Chrome (Version 94.0.4606.81) to frequently freeze up completely, instead of opening the file picker. It will still let me press Ctrl+W to close the tab, but other tabs will also remain unresponsive to mouse clicks. I am forced to close the entire browser. I could not reproduce this in Microsoft Edge however.

    const fileInput = document.querySelector("#fileInput");
    const dropArea = document.querySelector("#dropArea");
    const upload = document.querySelector("#upload");
    
    function onDragBegin(e) {
      e.preventDefault();
      e.dataTransfer.dropEffect = "copy";
      dropArea.classList.add("dropArea-highlight");
      upload.classList.add("upload-highlight");
    }
    
    function onDragEnd(e) {
      e.preventDefault();
      dropArea.classList.remove("dropArea-highlight");
      upload.classList.remove("upload-highlight");
    }
    
    function onDrop(e) {
      fileInput.files = e.dataTransfer.files;
      fileInput.dispatchEvent(new Event("change"));
      e.preventDefault();
    }
    
    async function onChangeFileInput() {
      const { files } = this;
    
      dropArea.classList.remove("dropArea-highlight");
      upload.classList.remove("upload-highlight");
    
      const url = "/api/har";
      const formData = new FormData();
      formData.append("harFile", files[0]);
    
      fetch(url, {
        method: "POST",
        body: formData,
      }).then(async (res) => {
        if (!res.ok) {
          const text = await res.text();
          alert(text);
        }
    
        if (res.redirected) {
          window.location.href = res.url;
        }
      });
    }
    
    dropArea.ondragover = onDragBegin;
    dropArea.ondragenter = onDragBegin;
    dropArea.ondragleave = onDragEnd;
    dropArea.ondrop = onDrop;
    
    fileInput.addEventListener("change", onChangeFileInput);
.upload {
      border: 1px dashed var(--copytext-grey);
      background-color: #e7eaef;
    }
    
    .upload:hover {
      background-color: #e1e4ea;
      border-style: dotted;
    }
    
    .upload-icon {
      height: 64px;
      filter: invert(36%) sepia(13%) saturate(381%) hue-rotate(171deg)
        brightness(93%) contrast(91%);
      margin-bottom: 16px;
    }
    
    #dropArea {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: 4rem 1rem;
    }
    
    #dropArea:hover {
      cursor: pointer;
    }
    
    #dropArea h3 {
      color: #555d66;
      font-weight: bold;
    }
    
    #dropArea p {
      color: #676f77;
    }
    
    #fileInput {
      display: none;
    }
    
    .upload-highlight {
      background-color: #e1e4ea;
      border-style: dotted;
    }
    
    .dropArea-highlight {
      cursor: pointer;
    }
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <link rel="stylesheet" href="style.css">
      <script src="upload.js" defer></script>
    </head>
    <body>
    
      <div class="upload" id="upload">
        <label for="fileInput">
          <div id="dropArea">
            <img src="upload.svg" class="upload-icon">
            <h3>Drag and drop or click</h3>
            <p>to upload your file</p>
            <input type="file" name="harFile" id="fileInput" accept=".har">
          </div>
        </label>
      </div>
    
    </body>
    </html>

I have already made a bugreport, but in the meantime I need to find a fix to stop the browser from freezing up. How?

Upvotes: 3

Views: 2178

Answers (2)

dwjohnston
dwjohnston

Reputation: 11812

For anyone else encountering this, it may be as Kaiido suggests, an OS issue.

Try restarting your computer.

Upvotes: 0

Kaiido
Kaiido

Reputation: 136746

Given this is not your code that's faulty, it will be hard to workaround that issue. (my guess would be some badly registered file the OS has troubles getting the metadata from, or some network drives (dropbox, icloud) that aren't connecting correctly).

The only workaround I can think of would be the new File System Access API, which hopefully would not trigger Chrome's issue (I think they shouldn't need the same metadata). But I am absolutely not sure this will do either so please let me know since I can't repro that issue myself.
Also, this API is currently only supported in Chromium based browsers, so you'd still need an <input type=file> fallback for other browsers.

Live demo as a glitch since this API isn't available in sandboxed iframes.

// we need to be handling a click event
document.querySelector("button").onclick = async () => {
  if( !("showOpenFilePicker" in self) ) {
    console.error("unsupported browser, should fallback to <input type=file>");
    return;
  }

  const handles = await showOpenFilePicker();
  const file = await handles[0].getFile();
  // now you can handle the file as usual
  document.getElementById( "log" ).textContent = await file.text();
};

Upvotes: 4

Related Questions