1

I have 2 elements on a page an input type="file" and a button when the button is clicked, I want to check if the file selected on the input element still exists or not. Let's just say the file gets deleted or renamed after after being selected and before the button was clicked.

Is there a way to do this? Even just a simple alert code whether it exists or not would be helpful.. thank you

3
  • That is a weird edge case to test for. Commented Sep 4, 2017 at 2:21
  • Why do you need this? Shouldn't the data be uploaded as a blob, which you can use no matter what? Commented Sep 4, 2017 at 2:35
  • 1
    @clabe45, unless you do slice it, or convert it to arrayBuffer / dataURL the browser won't keep the actual File's data in memory, only direct pointers to the files on the disk. Commented Sep 4, 2017 at 2:40

3 Answers 3

3

You can use the URL.createObjectURL method which will create a direct pointer to your file on the disk.

Then to check whether it has been deleted/renamed or not, you can simply try to fetch it (either through the fetch API, or through XHR).

let url;
inp.onchange = e => {
  url = URL.createObjectURL(inp.files[0]);
  btn.disabled = false;
}
btn.onclick = e => {
  fetch(url)
    .then((r) => console.log("File still exists"))
    .catch(e => console.log("File has been removed or renamed"));
}
<input type="file" id="inp">
<button disabled id="btn">check if deleted</button>

ES5 version : (with a lot of quirks to handle... only tested in FF Safari and chrome)

var url;
inp.onchange = function(e) {
  url = URL.createObjectURL(inp.files[0]);
  btn.disabled = false;
}
btn.onclick = function(e) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url); // cache trick for Safari
  xhr.responseType = 'blob';
  var headers = { // Safari uses the cache...
    "Pragma": "no-cache",
    "Cache-Control": "no-store, no-cache, must-revalidate, post-check=0, pre-check=0",
    "Expires": 0,
    "Last-Modified": new Date(0), // January 1, 1970
    "If-Modified-Since": new Date(0)
  };
  for (var k in headers) {
    xhr.setRequestHeader(k, headers[k]);
  }
  xhr.onload = function(e) {
    if (xhr.response.size) {
      console.log("File still exists\n");
    } else { // chrome fires the load event
      console.log("File has been removed or renamed (load event)\n");
    }
  };
  xhr.onerror = function(e) { // sometimes it fires an error
    console.log("File has been removed or renamed (error event)\n");
  };
  try {
    xhr.send();
  } catch (e) { // sometimes it throws in FF
    console.log("File has been removed or renamed (caught)\n");
  }
}
<input type="file" id="inp">
<button disabled id="btn">check if deleted</button>

And fiddles for Safari which doesn't fetch BlobURIs from stacksnippet®'s null-origined iframes :
ES6, ES5

Sign up to request clarification or add additional context in comments.

Comments

0

Extending on @Kaiido answer: loading from URL like that will load the entire file. If the file is huge it will take very long time and/or will cause the browser to consume a lot of RAM. Tested on chrome with 8GB file - browser used around 8GB memory when using fetch. When using XHR it seemed not to eat up memory but the request took very long to complete. One possible workaround - check onprogress event of the XHR:

xhr.onprogress = function (e) {
  if (e.loaded > 0) {
    xhr.abort();
    console.log("File still exists");
  }
}

Comments

0

You can actually do this without a fetch or XHR and without reading the entire file into memory. To do that we try to read a single byte from the file, and if it fails then you know the file no longer exists. When the file's size is zero the read will succeed regardless of whether the file still exists, but we can just use a fetch in that case.

async function fileExists(file) {
  try {
    if(file.size == 0) {
      await fetch(URL.createObjectURL(file))
    } else {
      await file.slice(0, 1).arrayBuffer()
    }
    console.log("file exists")
    return true
  } catch(e) {
    console.log("file deleted")
    return false
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.