【问题标题】:HTML file input - lock the file once selectedHTML 文件输入 - 选择后锁定文件
【发布时间】:2017-09-07 09:06:09
【问题描述】:

在被<input type="file" />选中后,浏览器有什么办法可以“锁定”文件吗?现在我可以选择一个文件,使用 JavaScript 对其进行一些操作,同时我可以从磁盘中删除它,这会导致 JavaScript 代码出错。

编辑目标是确保在我使用 JavaScript 处理文件时不能删除该文件。

【问题讨论】:

    标签: javascript html file-locking


    【解决方案1】:

    不,没有办法。仅仅因为 JS 是一种客户端语言,即使在服务器端也是不可能的,因为您无法与用户计算机进行交互。为此,您需要桌面应用程序来获取文件,例如复制并锁定它。

    如果要实现,则必须在浏览器中实现。

    编辑添加:

    如果您考虑一下,为什么浏览器还没有实现这一点,也许是因为如果您在上传文件时离线怎么办?保持锁定状态?

    【讨论】:

      【解决方案2】:

      :您可以在内存中创建一个副本,并使用它来代替用户磁盘上的文件。
      您必须先阅读其内容并从那里创建一个新文件/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=&gt;r.blob()); 在重新加载或重定向时检索。
      如果你需要它存活更长时间(硬刷新会杀死 blobURI 的引用),那么使用 indexedDB。


      编辑回复question's edit

      显然,您将无法更改文件在用户磁盘上的权限,但您不需要这样做,因为您可以获取它的副本来使用。

      【讨论】:

      • 也许这个问题太模糊了。我的目标是确保文件不能被删除。无论如何,谢谢。
      • @andy250 有什么目的?通过将其保存在内存中,文件将不会被删除,并且只要您的会话处于活动状态,您就可以保留它(要使其比文档的生命周期更长,您可以为复制的 Blob 创建一个 blobURI)或者在 IndexedDB 中更长时间。如果您的目标确实是更改用户磁盘的权限,那么显然您不能。
      • 这样用户就不能删除我正在处理的文件。就像您使用 7zip 在计算机上压缩文件并尝试重命名/删除它一样 - 您不能。我不想更改文件权限。只需确保用户在我完成之前无法删除该文件。正如我在问题中所说的那样 - 我不想要也不能将它存储在内存中,这是错误的,甚至不适用于大于可用内存的文件。
      • @andy250 “正如我所说的……”*你在哪里说的?是的,您可以将其存储在内存中,对于大文件,您可以将它们存储在 indexedDB 中,正如我告诉您的那样。这将在磁盘上的某些部分创建仅对浏览器可用的副本。您所说的 lock 行为是操作系统之一,它只允许单个进程同时读取文件。只是因为7-zip还没有放出主动阅读,所以还不能修改。
      • 对不起,我以为我提到了。我明白您对 IndexedDB 的看法,但是在我看来,再次复制假设磁盘上的 20GB 只是为了“保留它”是一种矫枉过正的做法。 IndexedDB 的大小也没有限制吗?底线是我想锁定文件,而不是摆弄内存或复制它。如果浏览器无法做到这一点 - 就这样吧。
      猜你喜欢
      • 2011-04-29
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 2021-04-16
      • 2014-12-09
      • 2014-04-07
      • 1970-01-01
      相关资源
      最近更新 更多