javascript - 这是来自文件或浏览器内存的流式传输吗?
问题描述
在下面的代码中,看起来我可以流式传输本地文件而无需一次将其全部加载到内存中,因为对于较大的文件,我会得到多个块(见console.log(chunk.length);
下文)
const fileInput = document.getElementById('file-input');
const startButton = document.getElementById('start-button');
fileInput.addEventListener('change', () => {
console.log(fileInput.files);
});
startButton.addEventListener('click', () => {
if (fileInput.files && fileInput.files.length) {
const fileURL = URL.createObjectURL(fileInput.files[0]);
fetch(fileURL, {
method: 'GET',
cache: 'no-store'
}).then(response => {
response.body.pipeTo(
new WritableStream({
write: chunk => {
console.log(chunk.length);
},
abort: error => {
console.error(error);
},
close: () => {
URL.revokeObjectURL(fileURL);
}
})
);
});
}
});
<input type="file" id="file-input" />
<button id="start-button">start</button>
但我想知道的是,确实会const fileURL = URL.createObjectURL(fileInput.files[0]);
创建一个指向本地文件的链接,然后通过 ReadableStream 从 fetch 中读取该文件,还是将整个文件加载到浏览器内存中,而我看到的块是“人造的”或来自浏览器内存到 Javascript 虚拟机内存?
解决方案
URL.createObjectURL( Blob )
仅创建指向 Blob 资源的符号链接。
如果是用户磁盘上的文件,那么它只是磁盘上该文件的符号链接,如果您在磁盘上重命名或删除它,您的 blob-URI 将指向任何地方。
自己做测试:
let url;
inp.oninput = e => url = URL.createObjectURL( inp.files[0] );
btn.onclick = e => fetch( url )
.then( console.log )
.catch( console.error );
<ol>
<li> select a file <input type="file" id="inp"></li>
<li> rename it on your disk or delete it</li>
<li> <button id="btn">try to fetch it</button></li>
</ol>
Ps:如果是内存中的 Blob,它也只是一个符号链接,但它也会将此资源标记为活动的,因此会阻止垃圾收集器收集它,直到您撤销此 blob-URI。
推荐阅读
- javascript - 当鼠标悬停在选择框控件上时,选择框会在选择框控件上方显示其选项
- r - 在 R 中使用 asIgraph() 函数将网络对象转换为 igraph 对象时出错?
- xml - 无法通过 powershell 读取 xml 值
- lstlisting - 使用 lstlisting 在代码列表中切换语言
- sql - SQL查询返回每个用户和他们的朋友
- angular - 在 Angular 5 中使用 ngformly 从 json 创建时出错
- python - 使用 python 抓取网页 - 不断从 jquery 表中获取重复的第一行值
- sql - 在 SQL 中获取最新更新记录的要求
- javascript - NodeJS 包混淆
- reactjs - 指向另一个列表视图的列表视图