I'm just learning how to use the filereader now, and I duplicated an example I found online to experiment with, but for some reason, the filereader always returns an empty string.
First, I have an HTML form for the user to select a file, which then calls the script:
<input type="file" id="filelist" onchange="selectfile()">
Here's the script:
function selectfile() {
myFile = document.getElementById("filelist").files[0];
reader = new FileReader();
reader.readAsText(myFile);
myResult = reader.result;
alert(myFile.name);
alert(myResult);
alert(reader.error);
}
I have tried this with a number of different text files I typed up in Notepad, and in every case the results are the same. I'm only ever submitting one file through the html form.
The 3 alerts are for testing.
It displays the file name correctly.
It displays an empty string for the result.
It displays NULL for the error so it's not getting an error.
I searched around to see if there was something obvious here already, but couldn't find anything that seemed to point me in the right direction.
Thoughts?
The FileReader object is not ready yet. You need to add an onload event listener to the reader and then make a call to the readAsText method. You can then access the file contents from inside the callback function.
MDN docs - https://developer.mozilla.org/en-US/docs/Web/API/FileReader/result
function selectfile() {
myFile = document.getElementById("filelist").files[0];
reader = new FileReader();
reader.onload = () => {
myResult = reader.result;
alert(myFile.name);
alert(myResult);
alert(reader.error);
};
reader.readAsText(myFile); // only accessible when the FileReader is loaded
}
<input type="file" id="filelist" onchange="selectfile()">
Related
Maybe naive question but I'm wondering this:
I have an html input allowing me to find a local file on my computer. <input type="file" id="importFile">
From this input, i create a FileReader in js to display the text file content on my page
var search_file = document.getElementById("search_file")
search_file.addEventListener('change', function(){
var reader = new FileReader();
var tmp = [];
reader.readAsText(file_to_survey);
reader.onload = function(e) {
var contents = e.target.result;
//function to edit html thanks to content//
}, false);
This part is actually working well BUT if I edit or replace the file I targeted (with exact same file name), I'm not able to display the file without to search it again with the html input mentionned above.
Is there a way to keep trace of my file even after edition?
Many thanks for your help. I dug quiet a lot to solve my problem but maybe I'm thinking the wrong way. Any clue would be nice.
Because that's how the input type=file element works, and to my best knowledge there is no way for you to force the browser to automatically re-read a file from the user's hard drive without their express consent.
You can put the change handler of the file input in a separate function, and call that function when needed.
function loadFile () {
var reader = new FileReader();
reader.addEventListener('load', function () {
file = reader.result;
// Handle the changes here
console.log(file);
});
reader.readAsText(fileField.files[0]);
}
const fileField = document.getElementById('load'),
reloadBut = document.getElementById('reload');
let file;
reloadBut.addEventListener('click', loadFile);
fileField.addEventListener('change', loadFile);
<input type="file" id="load">
<button id="reload">Load</button>
A separate button is used to reload the file in this snippet, but you can call loadFile where ever you need, ex. in an interval or from some event handler knowing the file was changed etc.
Note: This works in Chrome only, other browsers seem to lose the reference to the file browsed into file input when the file is changed. Also, the file must be properly closed after saving, before reloading.
I need to get the name, format and content of a browsed file only, multiple files not required. Even I cant use any HTML5 API/jQuery. Could you please guide me, using only pure JavaScript how do I solve this.
Here is the fiddle:
[https://jsfiddle.net/summtz8m/][1]
After getting all I need to click ImportASN1 button to POST data in REST service.
Here is my HTML
<button class="ebBtn" id="importButt" name="importButt"><span>Import ASN1</span></button><input type="file" id="myfile" name="myfile"><p id="contents"></p>
Here is my JS
var file = document.getElemtById("myfile").files[0];
console.log(file);
if (file) {
// create reader
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function(e) {
// browser completed reading file - display it
console.log(e.target.result);
};
}
Your current code runs on page load. But at that time the file input is not filled out yet! Instead, listen to the click event on the button, or the change event on the file input.
In addition, there is a typo: document.getElemtById should be document.getElementById. Use the developer console in your browser (F12 → Console in many browsers) to find these errors.
The file name will then be present in the file.name property.
<script>
document.getElementById("myfile").addEventListener('change', function(ev) {
var file = ev.target.files[0];
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function(e) {
console.log(file.name, e.target.result);
};
});
</script>
I have written the code below to display the text from a local file using the file API but when I click the button, nothing happens. I get the following error when I inspect the element in the browser. What am I doing wrong?
Uncaught TypeError: Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'.
<!DOCTYPE html>
<html>
<body>
<p>This example uses the addEventListener() method to attach a click event to a button.</p>
<button id="myBtn">Try it</button>
<pre id="file"></pre>
<script>
document.getElementById("myBtn").addEventListener("click", function(){
var file = "test.txt"
var reader = new FileReader();
document.getElementById('file').innerText = reader.result;
reader.readAsText(file);
});
</script>
</body>
</html>
You've made a couple of errors.
The one that the error message is complaining about is that you are trying to select a file using a hard coded string. You cannot determine which file gets loaded. The File API will only allow you to read files that are selected by the user via a File input.
The second is that you are trying to read the result property of the reader before you've read the file. You need an event handler to do that (because file reading, like Ajax, is asynchronous).
document.getElementById("myBtn").addEventListener("click", function() {
var reader = new FileReader();
reader.addEventListener('load', function() {
document.getElementById('file').innerText = this.result;
});
reader.readAsText(document.querySelector('input').files[0]);
});
<input type="file">
<button id="myBtn">Try it</button>
<pre id="file"></pre>
To save the File content in innerHtml, you must first read the file. loadend event fires only when file is fully read, and you can access its content without errors:
var reader = new FileReader();
var fileToRead = document.querySelector('input').files[0];
// attach event, that will be fired, when read is end
reader.addEventListener("loadend", function() {
// reader.result contains the contents of blob as a typed array
// we insert content of file in DOM here
document.getElementById('file').innerText = reader.result;
});
// start reading a loaded file
reader.readAsText(fileToRead);
You can read more here - and here
As the others said, I noticed that the onload event is what's missing.
So I have a couple of different ways of showing how to make the reader do something, one for doing the readAsText and one for getting the data as a base64 byte string using readAsDataURL, which is better, in my opinion, since you don't have to worry about Unicode and other weird question mark characters. To see them in action, just flip the call in the listener between uploadFile(); and uploadFile1();. And I show a couple of different ways you can grab the file object, as well:
document.getElementById("myBtn").addEventListener("click", function() {
uploadFile1();
});
function uploadFile1(){
var f = myInput.files[0];
var reader = new FileReader();
reader.onload = processFile(f);
reader.readAsText(f);
}
function uploadFile(){
var f = document.querySelector('input').files[0];
var reader = new FileReader();
reader.onload = processFile(f);
reader.readAsDataURL(f);
}
function processFile(theFile){
return function(e) {
// Use the .split I've included when calling this from uploadFile()
var theBytes = e.target.result; //.split('base64,')[1];
document.getElementById('file').innerText = theBytes;
}
}
<input id="myInput" type="file">
<button id="myBtn">Try it</button>
<span id="file"></span>
And normally I would think you should be able to just do:
<input type="button" onclick="uploadFile()" id="myBtn">Try it</button>
instead of having to add that listener, but it wasn't working in JSFiddle for some reason.
https://jsfiddle.net/navyjax2/heLmxegn/1/
Well! not sure about the others, but in my case it was solved by using fileObjects[0].file
A good way to look at it would be to print your 'files' or 'fileObjects' in the console and then see whether you require the .file in the end.
i'm currently trying to upload a file to my server. But i'm not really sure how to do this with readAsArrayBuffer. This works if I use readAsBinaryString.
If i try to console.log it only returns 'arrayBuffer: {}'.
After I've tried to upload it, i can see inside post that only a empty object was sent. If I use readAsBinaryString, I see a bunch of binary code.
var file = document.getElementById('my_file').files[0],
reader = new FileReader();
reader.onloadend = function(e){
console.log(e.target.result);
$scope.image = e.target.result;
}
reader.readAsArrayBuffer(file);
How can I see my file, so I know it's working when using readAsArrayBuffer?
If more code is needed let me know! Thanks.
According to ArrayBuffer documentation
You can not directly manipulate the contents of an ArrayBuffer; instead, you create one of the typed array objects or a DataView object which represents the buffer in a specific format, and use that to read and write the contents of the buffer.
So as I commented before probably console.log doesn't know how to represent the buffer and therefore it simply outputs arrayBuffer: {}.
If you want to show something in the console you need to use a typed array or a DataView. For example using an Int8Array:
reader.onloadend = function (e) {
console.log(e);
console.log(new Int8Array(e.target.result));
};
See demo
If you want to upload am image then you have to convert it into base64 format. You can do it either by using canvas element or by using Filereader.If you are using Filereader then you have to use readAsDataURL()
You can refer MDN for this
https://developer.mozilla.org/en-US/docs/Web/API/FileReader.readAsDataURL
also you can use canvas element
Convert an image to canvas that is already loaded
Using the filereader API it is possible to show a preview of the file, by reading the file with readAsDataURL
What I am trying to do is:
The user selects a file
A preview is shown, so that the user has some feedback.
If the user is satisfied, he submits the data to the backend.
Implementing step 3 can be done by re-reading the file with readAsBinaryString, but this looks problematic because the data could have disappeared or changed on disk. So What I would like is to convert the data returned from readAsDataURL to the format returned by readAsBinaryString. How can I do this?
Another alternative would be to submit the data to the backend as returned by readAsDataURL, but I would like to avoid that, since that would require special handling on the backend in my case.
Like CBroe said, you dont need to read the file twice.
JS :
handleFileSelectThumbFile(evt){
var files = evt.target.files;
var file = files[0];
// You can get the mime type like this.
var thumbMIME = files[0]['name'].split('.').pop();
if (files && file) {
var reader = new FileReader();
reader.onload = function(readerEvt) {
// Split the readerEvt.target.result by a ','.
// You can send the binaryString variable to the server.
// Its base64 encoded already.
var binaryString = readerEvt.target.result.split(',')[1];
// Set the image preview to the uploaded image.
$('.img-preview').prop('src', readerEvt.target.result);
}.bind(this);
reader.readAsDataURL(file);
}
}
HTML :
<input type="file" onChange={this.handleFileSelectThumbFile} required/>
<img src='http://placehold.it/300' class='img-preview'/>
You can read the MIME type from the first part of readerEvt as well. Look at CBroe's comment above.