我的页面上有 2 个元素 输入类型=“文件”和按钮 单击按钮时,我想检查输入元素上选择的文件是否仍然存在。假设文件在选择之后和单击按钮之前被删除或重命名。
有办法做到这一点吗?即使只是一个简单的警报代码,无论它是否存在都会有帮助..谢谢
URL.createObjectURL
方法,该方法将创建指向磁盘上文件的直接指针。
然后要检查它是否已被删除/重命名,您可以简单地尝试获取它(通过
fetch
API,或通过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 版本: (有很多怪癖需要处理...仅在 FF Safari 和 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>
还有 Safari 的小提琴,它不会从 stacksnippet® 的 null 起源的 iframe 中获取 BlobURI :
ES6、ES5
扩展 @Kaiido 答案:从 URL 加载将加载整个文件。如果文件很大,则需要很长时间和/或会导致浏览器消耗大量 RAM。在 chrome 上使用 8GB 文件进行测试 - 使用 fetch 时浏览器使用大约 8GB 内存。使用 XHR 时,它似乎不会消耗内存,但请求需要很长时间才能完成。一种可能的解决方法 - 检查 XHR 的进度事件:
xhr.onprogress = function (e) {
if (e.loaded > 0) {
xhr.abort();
console.log("File still exists");
}
}
实际上,您可以在不进行 fetch 或 XHR 的情况下完成此操作,并且无需将整个文件读入内存。为此,我们尝试从文件中读取单个字节,如果失败,那么您就知道该文件不再存在。当文件大小为零时,无论文件是否仍然存在,读取都会成功,但在这种情况下我们可以只使用 fetch。
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
}
}