问题
Currently I use a pattern like the following to read the first 3 characters of a series of files:
var files = e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) {
var fr = new FileReader();
fr.onload = function(e) {
var first_three_chars = e.target.result.substr(0,3);
}
fr.readAsText(f);
}
The trouble is that I'm only interested in the first 3 characters of the file, whereas this method reads the entire file, wasting lots of memory and time. How can I quickly iterate over the files, simply taking quick peeks at the first characters?
Edit: slice() was the answer, thanks sshen. Here's how I did it:
var files = e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) {
var fr = new FileReader();
fr.onloadend = function(e) {
if (e.target.readyState == FileReader.DONE) {
var first_three_chars = e.target.result;
}
};
var blob = f.slice(0, 3);
fr.readAsText(blob);
}
回答1:
You can use the .slice
method. You can read more here
var reader = new FileReader();
reader.onloadend = function(evt)
{
if (evt.target.readyState == FileReader.DONE) // DONE == 2
{
alert(evt.target.result);
}
};
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
回答2:
Not enough rep to comment, so putting some warnings about @Stu Blair solution here:
With the Blob.slice
method you are taking the bytes from the Blob, not the characters.
For example, this won't work:
const blob = new Blob(['😀'], {type: 'text/plain'});
const fr = new FileReader();
fr.readAsText(blob); // Fine, fr.result will be '😀'
fr.readAsText(blob.slice(0, 2)); // Not good, fr.result will be '��'
You will have to use FileReader.readAsArrayBuffer
to get the bytes. If your encoding is something like utf-8 you will have to read from the beginning.
回答3:
Either way you still have to go through the list of files, the contents of the FileList interface. The reason you're reading in the entire file is when you attach onload to every file and call readAsText() If you don't want to read in the entire file, just register an event handler that gets called back with the filelist before the files are loaded and goes through it. Something like this, where you attach to a form submission or something that expects to get the file list as part of its event object, without reading each one first.
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) {
var fileName = f.name.substr(0,3);
output.push('<strong>', fileName, '</strong>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
来源:https://stackoverflow.com/questions/14842214/html5-filereader-how-to-only-read-the-first-n-characters-of-a-file