Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I find out if a to-be-uploaded file was deleted before submitting?

Is there a browser compatible (in my case >IE9, Firefox and Chrome) way to catch the edge case that a file, that was supposed to be uploaded in a HTML form, was renamed or deleted on user's PC and hence could not be submitted?

I want to show an error to the user in that case after the impossible submit.

like image 805
k0pernikus Avatar asked Oct 01 '22 06:10

k0pernikus


2 Answers

  • If you select a file in IE and delete it afterwards in the file system, Windows will only hide the file, it is not deleted and the content can be read. So you don't have to worry about IE.
  • Chrome adjusts the file size (input.files[0].size) to 0 when you delete a file. Sadly, Firefox does not do this.

A workaround, which uses the FileReader API (works in IE 10+, Chrome, Firefox):

<input type="file" id="fileInput" />
<input type="button" onClick="checkDeleted();" value="Check"/>

<script>
    function checkDeleted() {
        input = document.getElementById('fileInput');
        if (input.files.length > 0) {
            var file = input.files[0];
            var fr = new FileReader();
            fr.onload = function (e) {
                alert("File is readable");
            };
            fr.onerror = function (e) {
                if (e.target.error.name == "NotFoundError") {
                    alert("File deleted");
                }
            }
            fr.readAsText(file);
        } else {
            // no file choosen yet
        }
    }
</script>

Working fiddle here.

like image 131
Manuel Allenspach Avatar answered Oct 13 '22 00:10

Manuel Allenspach


Base on @CommonGuy's answer, I tried it out and have tuned an optimized version.(tested with latest Chrome and Firefox.)

Note: To predict if a file CAN be read and tranferred. no matter file deleted, modified or permission changed, which may result in upload error, so we try to read the last byte(considerations for performance and firefox compatibility).

function tryReadingFile(file) {
  return new Promise((resolve, reject)=> {
    if (!(file instanceof File)) {
      reject(new Error('Not a File'));
      return;
    }
    let r = new FileReader();
    r.onload = (e)=> {
      resolve();
    };
    r.onerror = (e)=> {
      reject(r.error);
    };
    r.readAsArrayBuffer(file.size > 0 ? file.slice(-1) : file);
  });
}

function $(s, c) {
  return (c ? c : document).querySelector(s);
}
let currentFile;
function setSelectedFile(file) {
  currentFile = file;
  $('#output').innerHTML = file ? 'pending' : '';
}
function handleTestClick() {
  if (!currentFile) {
    return;
  }
  tryReadingFile(currentFile).then((ok)=> {
    $('#output').value = 'OK';
  }, (e)=> {
    $('#output').value = e.toString();
  });
}
<div>
  Step 1: select a file<br/>
  <input type="file" id="input" onchange="setSelectedFile(event.target.files[0])"/><br/>
</div>
<br/>
<div>
  Step 2: delete the file<br/>
  goto your file manager, and rename / delete / modify the file<br/>
</div>
<br/>
<div>
  Step 3: Test if the selected file can be read (and is ready to upload)<br/>
  <button type="button" onclick="handleTestClick()">Test</button><br/>
  <output id="output"></output>
  <div style="height:100px;"></div>
</div>
like image 22
fuweichin Avatar answered Oct 12 '22 22:10

fuweichin