【发布时间】:2017-09-07 09:06:09
【问题描述】:
在被<input type="file" />选中后,浏览器有什么办法可以“锁定”文件吗?现在我可以选择一个文件,使用 JavaScript 对其进行一些操作,同时我可以从磁盘中删除它,这会导致 JavaScript 代码出错。
编辑目标是确保在我使用 JavaScript 处理文件时不能删除该文件。
【问题讨论】:
标签: javascript html file-locking
在被<input type="file" />选中后,浏览器有什么办法可以“锁定”文件吗?现在我可以选择一个文件,使用 JavaScript 对其进行一些操作,同时我可以从磁盘中删除它,这会导致 JavaScript 代码出错。
编辑目标是确保在我使用 JavaScript 处理文件时不能删除该文件。
【问题讨论】:
标签: javascript html file-locking
不,没有办法。仅仅因为 JS 是一种客户端语言,即使在服务器端也是不可能的,因为您无法与用户计算机进行交互。为此,您需要桌面应用程序来获取文件,例如复制并锁定它。
如果要实现,则必须在浏览器中实现。
编辑添加:
如果您考虑一下,为什么浏览器还没有实现这一点,也许是因为如果您在上传文件时离线怎么办?保持锁定状态?
【讨论】:
是:您可以在内存中创建一个副本,并使用它来代替用户磁盘上的文件。
您必须先阅读其内容并从那里创建一个新文件/Blob:
let theFile = null;
inp.onchange = async function(e) {
theFile = await saveBlob(inp.files[0]);
btn.disabled = false;
inp.disabled = true;
}
btn.onclick = e => {
console.log(theFile);
let reader = new FileReader();
// to prove it's really still there
reader.onload = e => console.log(new Uint8Array(reader.result));
reader.onerror = e => console.log(e);
reader.readAsArrayBuffer(theFile.slice(0, 4));
}
function saveBlob(blob) {
let reader = new FileReader();
return new Promise((res, rej) => {
reader.onload = e => {
if (blob instanceof File) {
// tries to keep it as a File, but beware some implementations still have bugs
res( new File([reader.result], blob.name, {type: blob.type}) );
} else {
res( new Blob([reader.result], {type: blob.type}) );
}
};
reader.onerror = rej; // already removed ???
reader.readAsArrayBuffer(blob);
});
}
<input type="file" id="inp">
<button id="btn" disabled>I did remove it from disk</button>
另一种方法是将其存储在 indexedDB 中。
然后,您可以使用此副本,并确保无论用户如何处理原始文件,它都会保留在内存中。
如果您需要将其保存的时间超过文档的生命周期,您可以创建一个 blobURI (URL.createObjectURL(theFile)),您可以将其存储在 localStorage 中,并使用 fetch(blobURI).then(r=>r.blob()); 在重新加载或重定向时检索。
如果你需要它存活更长时间(硬刷新会杀死 blobURI 的引用),那么使用 indexedDB。
编辑回复question's edit。
显然,您将无法更改文件在用户磁盘上的权限,但您不需要这样做,因为您可以获取它的副本来使用。
【讨论】: