Check If File Has Changed Using HTML5 File API

Check if file has changed using HTML5 File API

I don't believe the File API has any event for the file changing, just progress events and the like.

Update August 2020: The alternative below no longer works, and the specification specifically disallows it by saying that the File object's information must reflect the state of the underlying file as of when it was selected. From the spec:

User agents should endeavor to have a File object’s snapshot state set to the state of the underlying storage on disk at the time the reference is taken. If the file is modified on disk following the time a reference has been taken, the File's snapshot state will differ from the state of the underlying storage.


You could use polling. Remember the lastModifiedDate of the File, and then when your polling function fires, get a new File instance for the input and see if the lastModifiedDate has changed.

This works for me on Chrome, for instance: Live Copy | Source

(function() {
var input;
var lastMod;

document.getElementById('btnStart').onclick = function() {
startWatching();
};
function startWatching() {
var file;

if (typeof window.FileReader !== 'function') {
display("The file API isn't supported on this browser yet.");
return;
}

input = document.getElementById('filename');
if (!input) {
display("Um, couldn't find the filename element.");
}
else if (!input.files) {
display("This browser doesn't seem to support the `files` property of file inputs.");
}
else if (!input.files[0]) {
display("Please select a file before clicking 'Show Size'");
}
else {
file = input.files[0];
lastMod = file.lastModifiedDate;
display("Last modified date: " + lastMod);
display("Change the file");
setInterval(tick, 250);
}
}

function tick() {
var file = input.files && input.files[0];
if (file && lastMod && file.lastModifiedDate.getTime() !== lastMod.getTime()) {
lastMod = file.lastModifiedDate;
display("File changed: " + lastMod);
}
}

function display(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
})();
<input type='file' id='filename'>
<input type='button' id='btnStart' value='Start'>

Check if local file has changed

This will be possible again if/when the Native File System API is implemented in browsers. It will be partially enabled in Google Chrome 85, scheduled for release in October 2020.

Unlike the FileReader API it requires a explicit user interaction, so you'd do something like this:

myFileInput.addEventListener('change', async (e) => {
const fh = await window.chooseFileSystemEntries()
// fh is now a FileSystemFileHandle object
// Use fh.getFile() to get a File object
})

HTML5 File API simple check if file exists

You have to read the file. The following example is based on this demo from HTML5Rocks (it catches all errors, you might want to filter the different error types):

    var errorHandler = function() {
// File is not readable or does not exist!
};
fs.root.getFile('log.txt', {}, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function() {
// The file exists and is readable
};
reader.readAsText(file);
}, errorHandler);
}, errorHandler);

The synchronous method is only available to Web Workers, due to their blocking nature. The error handling is slightly different.

Can a file be changed after it has already been selected in input type=file and still have its text read?

No, there is no reliable way.

When selecting a file from an <input type="file"> the browser gets a pointer to the file on disk along with some metadata provided by the OS. Luckily, it doesn't save the file's data in memory (would be quite hard to upload multi-GB files otherwise), and it doesn't lock the file on disk either.

So the user can indeed edit the file on disk, and they can even remove it from the disk.
However, most browsers will use the metadata provided by the OS at the moment of picking it in order to read the file through a FileReader.

This means that if your file was 120KB when picked, then edited to make it a 100KB file, the browser will ask for data that doesn't exist anymore, and the reader will crash.

You can of course force the browser to store the full data in memory at the moment of picking it, e.g

blob = new Blob( [ await file.arrayBuffer() ], { type: file.type } );

here blob holds in memory the data that file was pointing to at the moment it's been called.

But blob is not connected anymore with the file on disk, so if your user does edit the file on disk, blob won't be changed.

Note that Firefox will actually be able to handle edited files through the Blob methods (arrayBuffer() and text()) at least on macOS (I guess OS matters here), but their FileReader will still fire an Error. Chrome just throws in both cases.
In the same way, fetching the file through XHR or fetch will throw in Chrome (but not in FF if the file only has been edited and still exists).

HTML5: Is file change notification in the API?

There is no API for file change notifications.

FileAPI doesn't update the files size when user makes file changes (non-webkit browsers)

It seems that you're get the size property from the directly, and because the value in this form element is not changed it's likely that Firefox doesn't update the size property as well.

As workaround, you can check the length of the content you have read. So instead of file.size have evt.target.result.length.

However, it's definitely a bug to me so you have done well to add it on Bugzilla!

Update:
You can still use the string version of slice. Otherwise, if you prefer (or the result is a particular type of data), you can create from evt.target.result a new Blob object (The File Object use this interface) where you can use both size property and slice method.

Client Checking file size using HTML5?

This works. Place it inside an event listener for when the input changes.

if (typeof FileReader !== "undefined") {
var size = document.getElementById('myfile').files[0].size;
// check file size
}

How to detect input type=file change for the same file?

You can trick it. Remove the file element and add it in the same place on change event. It will erase the file path making it changeable every time.

Example on jsFiddle.

Or you can simply use .prop("value", ""), see this example on jsFiddle.

  • jQuery 1.6+ prop
  • Earlier versions attr


Related Topics



Leave a reply



Submit