引用已撤消的对象URL

时间:2019-06-22 01:28:13

标签: javascript html

我有一个UI,用户可以在其中加载各种文件,其中包括图像。这些图像带有预览缩略图,非常类似于此示例:

https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications

要点:

<input type="file" onchange="handleFiles(this.files)">

JavaScript:

function handleFiles(e) {

    …

    const img = document.createElement("img");
    img.src = window.URL.createObjectURL(file);
    img.height = 60;
    img.onload = function() {
        window.URL.revokeObjectURL(this.src);
    }
    li.appendChild(img);

    …
}

我的问题是关于revokeObjectURL。它说

  

设置图像的加载事件处理程序以释放对象URL,因为一旦加载图像就不再需要它。可以通过调用window.URL.revokeObjectURL()方法并传入img.src指定的对象URL字符串来完成。

但是,如果这样做,则无法在第二张图像上直接引用src。如:

other_image.src = thumbnail.src;

可以简单地将其撤消吗?仅在我动态删除缩​​略图时才将其撤消吗?

或者;还有另一种(出于某种原因)更好的方式来引用图像吗?

示例代码:

const 
  no_files = document.getElementById("no_files"),
  thumbs = document.getElementById("thumbs"),
  preview = document.getElementById("preview")
  ;
  
function handle_files(files)
{
  if (!files.length) {
    no_files.classList.remove('hide');
  } else {
    no_files.classList.add('hide');
    for (let i = 0; i < files.length; i++) {
      const li = document.createElement("li");
      thumbs.appendChild(li);
      
      const img = document.createElement("img");
      img.src = window.URL.createObjectURL(files[i]);
      /* 
       * Commented out to alow ref of src
       *
      img.onload = function() {
        window.URL.revokeObjectURL(this.src);
      }
      */
      li.appendChild(img);
    }
  }
}
function do_preview (e) {
  if (e.target.tagName == 'IMG')
    preview.src = e.target.src;
}
thumbs.addEventListener('mouseenter', do_preview, true);
html, body {
  height: 100%;
}
* {
  margin: 0;
  padding: 0;
}
.hide {
  display: none;
}
ul {
  list-style: none;
}
li img {
  max-width: 40px;
  margin: 5px;
  border: 1px solid #987;
}
.images {
  display: flex;
  padding: 10px;
  overflow: auto;
  height: 90%;
}
#preview {
  max-width: 300px;
  margin: 5px;
}
.list, .display {
  border: 1px solid #789;
  padding: 5px;
  height: 90%;
}
.list {
  flex: 0 0 auto;
  overflow-y: scroll;
}
.display {
  flex: 1;
}
<input type="file" multiple accept="image/*"  onchange="handle_files(this.files)">
<div class="images">
  <div class="list">
    <p id="no_files">No files selected!</p>
    <ul id="thumbs"></ul>
  </div>
  <div class="display">
    <img id="preview">
  </div>
</div>

1 个答案:

答案 0 :(得分:1)

由于这些blob URL指向来自用户磁盘的文件,因此最好不要将其撤消。它们只是指向磁盘的直接指针,它们(几乎)没有在内存中保存任何内容。

如果它们指向内存中的某个文件(例如,使用Blob构造函数获取或生成的文件),那么一旦不再需要它们就将其吊销可能很重要,这样它们所指向的Blob就可以可以回收已收集的垃圾和已分配的内存。但是,如果您保留对指向的Blob的引用或以后需要它们,那么只要您确保不要创建过多的Blob,也可以不撤销它。