HTML 文件输入 - 选择后锁定文件
HTML file input - lock the file once selected
在 <input type="file" />
编辑 select 后,浏览器是否有任何方法可以 "lock" 文件?现在我可以 select 一个文件,用 JavaScript 开始一些操作,同时我可以从我的磁盘中删除它,这会导致 JavaScript 代码出错。
EDIT 目标是确保在我使用 JavaScript.
处理文件时无法删除该文件
不,没有办法。仅仅因为 JS 是一种客户端语言,即使在服务器端也是不可能的,因为您无法与用户计算机进行交互。为此,您需要您的桌面应用程序以文件为例复制并锁定它。
如果要实现,则必须在浏览器中实现。
编辑补充:
如果您考虑一下为什么浏览器尚未实现这一点,可能是因为如果您在上传文件时脱机怎么办?保持锁定状态?
是 : 您可以在内存中创建一个副本,并使用它来代替用户磁盘上的文件。
您必须先阅读其内容并从那里创建一个新的 File/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。
显然您无法更改文件在用户磁盘上的权限,但您不需要这样做,因为您可以获得它的副本以供使用。
在 <input type="file" />
编辑 select 后,浏览器是否有任何方法可以 "lock" 文件?现在我可以 select 一个文件,用 JavaScript 开始一些操作,同时我可以从我的磁盘中删除它,这会导致 JavaScript 代码出错。
EDIT 目标是确保在我使用 JavaScript.
处理文件时无法删除该文件不,没有办法。仅仅因为 JS 是一种客户端语言,即使在服务器端也是不可能的,因为您无法与用户计算机进行交互。为此,您需要您的桌面应用程序以文件为例复制并锁定它。
如果要实现,则必须在浏览器中实现。
编辑补充:
如果您考虑一下为什么浏览器尚未实现这一点,可能是因为如果您在上传文件时脱机怎么办?保持锁定状态?
是 : 您可以在内存中创建一个副本,并使用它来代替用户磁盘上的文件。
您必须先阅读其内容并从那里创建一个新的 File/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。
显然您无法更改文件在用户磁盘上的权限,但您不需要这样做,因为您可以获得它的副本以供使用。