只读取 Javascript 中文件的第一个块
Read only the first chunk of a file in Javascript
我们有一个基于浏览器的界面,用户可以在其中选择要上传的文件。
选择文件后,它会加载到 FileReader 对象中,内容会加载到内存中并通过调用 FileReader.readAsText() 进行验证。
这适用于 50MB 的文件(需要 2-3 秒)。
但是,当您的文件大小达到 200MB 时,甚至在 20 分钟后,文件仍未完成读取并且处理器保持在 100% 的利用率。
我认为这是由于内存耗尽造成的,因为整个文件都被加载到一个变量中。
有没有什么方法可以分块加载文件的内容,而不是将整个文件加载到一个巨大的、吸内存的怪物中?
我们只需要验证文件的前 1KB 左右,所以我们需要做的就是读取第一个有效块,然后完成。
概念证明,自己测试:
<form>
<input type="file" /> File
</form>
<script type="text/javascript">
var input = document.getElementsByTagName('input')[0];
input.onchange = function(e) {
var file = input.files[0];
var reader = new FileReader();
reader.onload = function() {
var file_contents = reader.result;
alert('File Read. Size:' + file_contents.length);
};
reader.readAsText(file);
};
</script>
我会利用 File 实现的 Blob 接口,它的 .stream()
方法 returns a ReadableStream
.
async function validateFile(file) {
const stream = file.stream();
const reader = stream.getReader();
let bytesRead = 0;
let exhausted = false;
while (bytesRead < 1e3 && !exhausted) {
const {value, done} = await reader.read();
// value is a Uint8Array
bytesRead += value ? value.length : 0;
exhausted = done;
}
}
我们有一个基于浏览器的界面,用户可以在其中选择要上传的文件。
选择文件后,它会加载到 FileReader 对象中,内容会加载到内存中并通过调用 FileReader.readAsText() 进行验证。
这适用于 50MB 的文件(需要 2-3 秒)。 但是,当您的文件大小达到 200MB 时,甚至在 20 分钟后,文件仍未完成读取并且处理器保持在 100% 的利用率。
我认为这是由于内存耗尽造成的,因为整个文件都被加载到一个变量中。
有没有什么方法可以分块加载文件的内容,而不是将整个文件加载到一个巨大的、吸内存的怪物中?
我们只需要验证文件的前 1KB 左右,所以我们需要做的就是读取第一个有效块,然后完成。
概念证明,自己测试:
<form>
<input type="file" /> File
</form>
<script type="text/javascript">
var input = document.getElementsByTagName('input')[0];
input.onchange = function(e) {
var file = input.files[0];
var reader = new FileReader();
reader.onload = function() {
var file_contents = reader.result;
alert('File Read. Size:' + file_contents.length);
};
reader.readAsText(file);
};
</script>
我会利用 File 实现的 Blob 接口,它的 .stream()
方法 returns a ReadableStream
.
async function validateFile(file) {
const stream = file.stream();
const reader = stream.getReader();
let bytesRead = 0;
let exhausted = false;
while (bytesRead < 1e3 && !exhausted) {
const {value, done} = await reader.read();
// value is a Uint8Array
bytesRead += value ? value.length : 0;
exhausted = done;
}
}