Can't assign base64 string to a class property - javascript - javascript

my goal is to make an upload of an image, I have a method whre I want to assign the base64 string to the class method file, the problem is that when I try to get the value in the property, the result is undefined and I don't understand why. I whould like to assign the string to the property _file or return it in the method.
My code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<form action="" enctype="multipart/form-data">
<input type="file" />
<input id="btn" type="submit" value="submit" />
</form>
<script>
class File {
constructor() {
this._file;
}
setFile(file) {
const input = document.querySelector(file).files[0];
const reader = new FileReader();
reader.readAsDataURL(input);
reader.onload = function () {
this._file = reader.result.split(",")[1];
console.log(this._file);
};
}
getFile() {
console.log(this._file);
}
}
document
.getElementById("btn")
.addEventListener("click", function (event) {
event.preventDefault();
const file = new File();
file.setFile("input[type=file]");
file.getFile();
});
</script>

You have two subtle mistakes:
reader.onload = function() {
this._file = reader.result.split(",")[1];
console.log(this._file);
};
Here, the this keyword is not pointing to your File instance, it is pointing to reader. This can be resolved by using arrow functions:
reader.onload = () => {
this._file = reader.result.split(",")[1];
console.log(this._file);
};
Now, the this keyword is pointing to your File instance. Now you have another problem: readAsDataURL is asynchronous, that is, it does all the job in the background, like AJAX, without blocking the main thread. So if you have:
file.setFile("input[type=file]");
file.getFile();
Nothing guarantees that file.getFile() will print the updated value for _file, because you don't know if the reader has finished its job or not. So my recommendation is using a callback:
class File {
constructor() {
// ...
}
setFile(file, callback) {
const input = document.querySelector(file).files[0];
const reader = new FileReader();
reader.onload = () => { // when reader has finished
this._file = reader.result.split(",")[1]; // update _file property
callback(); // execute callback
};
reader.readAsDataURL(input);
}
getFile() {
console.log(this._file);
}
}
document.getElementById("btn").addEventListener("click", function(event) {
event.preventDefault();
const file = new File();
file.setFile("input[type=file]", function() {
// put here all the code that uses the file variable
file.getFile();
});
});
LIVE DEMO
class File {
constructor() {
// ...
}
setFile(file, callback) {
const input = document.querySelector(file).files[0];
const reader = new FileReader();
reader.onload = () => { // when reader has finished
this._file = reader.result.split(",")[1]; // update _file property
callback(); // execute callback
};
reader.readAsDataURL(input);
}
getFile() {
console.log(this._file);
}
}
document.getElementById("btn").addEventListener("click", function(event) {
event.preventDefault();
const file = new File();
file.setFile("input[type=file]", function() {
// put here all the code that uses the file variable
file.getFile();
});
});
<form action="" enctype="multipart/form-data">
<input type="file" />
<input id="btn" type="submit" value="submit" />
</form>

Related

How can I load text file in javascript using fileReader? [duplicate]

This question already has answers here:
Javascript read file without using input
(3 answers)
Closed 9 months ago.
I'm trying to load simple text file in javascript, unfortunately with no success.
my code is:
var my_text:any;
var my_file:File = new File([], "C:\\Users\\riki7\\Downloads\\classes.txt");
var reader = new FileReader();
reader.onload = function() {
my_text = reader.result;
};
reader.readAsText(my_file);
alert(my_text);
after this code runs, I would expect to see classes.txt file content in pop-up alert, instead I get 'undefined'.
my file contains a, b, c.
does anyone know what is my problem? maybe the first parameter for File() constructor?
You have to use html tag <input type="file" id="input" /> and then hung a event listener on it, like that
const inputElement = document.getElementById("input");
inputElement.addEventListener("change", handleFiles, false);
function handleFiles() {
const fileList = this.files; /* now you can work with the file list */
}
then after simply bypass your file into the FileReader
const reader = new FileReader();
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
reader.readAsDataURL(file);
And i guess that would be it.
You can find more examples there: https://developer.mozilla.org/en-US/docs/Web/API/File_API/Using_files_from_web_applications
Having your code where your alert runs upfront the callback function. If you need to see alter with the content, simply move your alert into the callback function:
reader.onload = function() {
my_text = reader.result;
alert(my_text);
};
because my_text is not ready when you call alert outside.
<input type="file" id="selectedFile">
<p id="display"></p>
<script>
var fr = new FileReader();
let test;
document.getElementById('selectedFile').addEventListener('change', x);
function x() {
fr.onload = ()=>{
document.getElementById('display').innerText = fr.result;
test = fr.result;
alert(fr.result);
}
fr.readAsText(this.files[0]);
}
</script>
<html>
<head>
<script>
var fileReadEvent = function(event) {
var input = event.target;
var reader = new FileReader();
reader.onload = function(){
var text = reader.result;
alert(text)
};
};
</script>
</head>
<body>
<input type='file' accept='text/plain' onchange='fileReadEvent(event)'><br>
</body>
</html>

JavaScript - Load a file twice in a row

Good day,
I have the following code to load a ".TXT" file into a web page
function load(event) {
let fr = new FileReader();
fr.onload = function() {
let load0 = JSON.parse(fr.result);
console.log(load0);
console.log("Ready!");
};
fr.readAsText(event.target.files[0]);
}
function loadInput(event) {
document.getElementById("loadInputButton").click();
}
<html>
<body>
<input type="button" onclick="loadInput(event)" />
<input id="loadInputButton" type="file" accept="text" onchange="load(event)" />
</body>
</html>
It works fine but only once. After I once load the file it will not work anymore. I try to load the same file again but the function produces nothing.
May I ask for your help solving it?
Thank you,
Eugene
Clear the value of the input after using it, so that the change event will fire when you select the same file.
function load(event) {
let fr = new FileReader();
fr.onload = function() {
let load0 = JSON.parse(fr.result);
console.log(load0);
console.log("Ready!");
event.target.value = '';
};
fr.readAsText(event.target.files[0])
}
function loadInput(event) {
document.getElementById("loadInputButton").click();
}
<html>
<body>
<input type="button" onclick="loadInput(event)" />
<input id="loadInputButton" type="file" accept="text" onchange="load(event)" />
</body>
</html>

P5JS Unable to access values of an object

I am using the LoadBytes function from P5.JS which returns an object but I am unable to access "object" via using ".bytes" or "['bytes']".
For some reason when running a live server it seems to work perfectly.
function get_rom () {
var fileList = document.getElementById("rom").files;
var fileReader = new FileReader();
if (fileReader && fileList && fileList.length) {
url = URL.createObjectURL(fileList[0])
return loadBytes(url)
}
}
function loadarom () {
object = get_rom()
print(object.bytes[1]) // <-- issue here
}
When using loadBytes() the returned object will not immediately have the bytes array populated. You need to use the callback parameter to loadBytes():
let loadBtn;
function setup() {
noCanvas();
noLoop();
loadBtn = createButton("Load Rom");
loadBtn.mousePressed(loadarom);
}
function get_rom(onSuccess) {
let fileList = document.getElementById("rom").files;
// Alternate method using FileReader has been commented out
// let fileReader = new FileReader();
/*
fileReader.addEventListener("load", function () {
// convert image file to base64 string
loadBytes(fileReader.result, onSuccess);
}); */
if (fileList && fileList.length) {
loadBytes(URL.createObjectURL(fileList[0]), onSuccess);
// fileReader.readAsDataURL(fileList[0]);
}
}
function loadarom() {
get_rom(obj => {
print(obj.bytes[0]);
})
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
</head>
<body>
<input id="rom" type="file" />
</body>
</html>
Barley don't need p5.js for such a easy task.
use blob.arrayBuffer()
<script type="module">
var file = new File(['abc'], 'abc.txt')
var bytes = new Uint8Array(await file.arrayBuffer())
console.log(bytes)
</script>
(SO! You should support top level await in a async IIFE fn or start adding type="module" to js-code

JavaScript - Reading file with HTML5 FileReader

I'm currently learning JavaScript and I'm struggling to read a txt file and use its contents in the program, what I have so far:
fileBtn.addEventListener("change", function()
{
var content = [];
var file = fileBtn.files[0];
readFile(file, function(data)
{
console.log(JSON.parse(data));
//content.push(JSON.parse(data)) doesn't work, data is undef.
});
});
and a function readFile
function readFile(file, f)
{
var reader = new FileReader();
reader.onload = function(evt)
{
f(evt.target.result);
};
reader.readAsText(file);
}
My txt file is currenty only containing a "1", and it logs this number to the console but I can't work with it, if I try to push it into an array the values is suddenly undefined. My goal is to use the content of the file in the program later on
1 . no need to use JSON.parse if the text file only contain string .
data is containing all the text file content
2 . you need to put var content = [];
globally and not inside the function readFile
follow this snippet of code i think it will solve your problem
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<label for="file-upload" class="custom-file-upload">
Custom Upload
</label>
<input id="file-upload" type="file" />
<input id="log-content" type="button" value="Click Me"/>
</body>
<script>
var content = [];
function readFile(file, f) {
var reader = new FileReader();
reader.onload = function (evt) {
f(evt.target.result);
};
var text = reader.readAsText(file);
}
var fileBtn = document.getElementById("file-upload");
var logContnt = document.getElementById("log-content");
logContnt.addEventListener("click", function () {
alert(content);
})
fileBtn.addEventListener("change", function () {
var file = fileBtn.files[0];
readFile(file, function (data) {
content.push(data);
});
});
</script>
</html>

FileReader returning undefined for File object in JQuery

Can some one tell me why when all the File attributes are printed properly why FileReader.readAsArrayBuffer() is returning undefined in the following code
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title of the document</title>
</head>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$( document ).ready(function() {
$( "#form" ).submit(function( event ) {
event.preventDefault();
var filevar=document.getElementById("file").files[0];
var reader=new FileReader() ;
console.log(filevar.name);
console.log(filevar.size);
console.log(filevar.type);
var file_contents= reader.readAsArrayBuffer(filevar);
console.log(file_contents);
});
});
</script>
<body>
<form action="" method="POST" id="form">
First name:<br>
<input type="text" name="firstname"><br>
Last name:<br>
<input type="text" name="lastname"><br>
Choose File : <input name="myFile" type="file" id="file">
<input type="submit" id="submit">
</form>
</body>
</html>
Reading a file is asynchronous. You have to wait until it's done.
var reader = new FileReader();
reader.onload = function(e){
let value = e.value; // alternatively reader.result
// do stuff with your value
};
reader.readAsArrayBuffer(filevar);
.readAsArrayBuffer does not return anything.
Alternatively, you can set up an async function for that so you don't have to use callbacks:
function readFile(file){
return new Promise((res, rej) => {
// create file reader
let reader = new FileReader();
// register event listeners
reader.addEventListener("loadend", e => res(e.target.result));
reader.addEventListener("error", rej);
// read file
reader.readAsArrayBuffer(file);
});
}
async function main(file){
// read file into typed array
let fileArrayBuffer = new Uint8Array(await readFile(file));
// do things with it
console.log(fileArrayBuffer);
}
// register event listener for input
document.querySelector("input[type=file]").addEventListener("change", e => {
let file = e.target.files[0];
main(file);
});
<input type="file">
FileReader is actually an async function. Some files are larger than others and so you do not want to lock the main thread.
If you want to see the result of the file. You should add a call back to the onload function of the reader.
var reader = new FileReader();
reader.onload = function(completionEvent) {
console.log(completionEvent);
// Set the result to whatever you need it as
}
reader.readAsArrayBuffer(filevar);

Categories