How to mainpulate file after reading it in Javascript/Vue - javascript

I have a method that gets the contents of the file and stores it into a string. My this.parseText is a global variable:
` openFile(event) {
const inputFile = event.target.files[0];
const readerObject = new FileReader();
let fileText = 'Empty';
readerObject.onload = function () {
fileText = readerObject.result;
this.parseText = fileText;
console.log(fileText);
};
readerObject.readAsText(inputFile);
return this.parseText;
},
`
I also have a button that when the user clicks on it, it should manipulate the string. The HTML is:
<input type="file" id="fileUpload" accept=".csv" #change="openFile"/> <button v-on:click="testButton">Test me!</button>
I have a function called:
testButton() {
console.log(this.parseText);
},
However when I console this, it does not print the content of the file. This is due to the openFile being asynchronous. How can I use javascript (no jQuery) to wait for this.parseText to contain the necessary String in order to manipulate it in my testButton() function?

Related

How to load file content to variable using FileReader

I would like to seek some help please regarding loading txt file content to variable using input element in javascript.
So i am working with java script file separate from html file, and when the user click on button to load the file from the html side as below:
<input type="file" id="selectedFile" accept=".txt" />
it fires the onchange event as below
document.getElementById('selectedFile').addEventListener('change', function () {
var fr = new FileReader();
fr.onload = function () {
document.getElementById('display').textContent = fr.result;
console.log(fr.result);
}
fr.readAsText(this.files[0]);
})
basically if i console log the fr.result as in the code up there, i can see the content with no issues, and also i have div element with id "display" and content gets updated no issues. however i am unable to get the fr.result to be stored into global variable and use it later on in my code.
I tried the below code:
let test = "";
document.getElementById('selectedFile').addEventListener('change', function () {
var fr = new FileReader();
fr.onload = function () {
document.getElementById('display').textContent = fr.result;
test = fr.result;
}
fr.readAsText(this.files[0]);
})
console.log(test);
but the test variable in console comes out empty and runs even before i choose the file with input element.
Any advices about what i missing here, and how i can get the file content using same method to be stored in variable?
Thanks!
I tried it it works like this, it was maybe because your event listener function was an anonymous function, and you can't call this in anonymous function
<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;
console.log(fr.result);
test = fr.result;
}
fr.readAsText(this.files[0]);
}
console.log(test);</script>

I want to extract a string from a text file and output it as a text file again

I want to extract a string from a text file, convert it to a word scrambler (I figured out that part) and output it in another text file.
I found some code to input a text file and extract the text:
<html>
<h4>Select un file con .txt extension</h4>
<input type="file" id="myFile" accept=".txt" />
<br /><br />
<div id="output"></div>
<script>
var input = document.getElementById("myFile");
var output = document.getElementById("output");
input.addEventListener("change", function () {
if (this.files && this.files[0]) {
var myFile = this.files[0];
var reader = new FileReader();
reader.addEventListener("load", function (e) {
output.textContent = e.target.result;
});
reader.readAsText(myFile);
}
});
</script>
</html>
Input text and extract a text file
<html>
<div>
<input type="text" id="txt" placeholder="Write Here" />
</div>
<div>
<input type="button"id="bt"value="Save in a File"onclick="saveFile()"/>
</div>
<script>
let saveFile = () => {
const testo = document.getElementById("txt");
let data = testo.value;
const textToBLOB = new Blob([data], { type: "text/plain" });
const sFileName = "Testo.txt";
let newLink = document.createElement("a");
newLink.download = sFileName;
newLink.href = window.URL.createObjectURL(textToBLOB);
newLink.style.display = "none";
document.body.appendChild(newLink);
newLink.click();
};
</script>
</html>
But I don't know how to output a string in the first code or how to connect it to the second code. Could someone please show me how to do it or explain how these codes work so that I could try to do it myself in JavaScript?
I will comment each line of JavaScript, that should help you understand.
<script>
/*This creates a global variable with the HTML element input in it. */
var input = document.getElementById("myFile");
/*This creates a global variable with the HTML element div with id output in it. */
var output = document.getElementById("output");
/* this 2 lines are used to set the source and the destination.
The first will get where you put your file, in this case it's the input element.
The second will get the div which content will be replaced by the content of your txt file. */
/* Here we tell to our input element to do something special when his value changes.
A change will occur for example when a user will chose a file.*/
input.addEventListener("change", function () {
/* First thing we do is checking if this.files exists and this.files[0] aswell.
they might not exist if the change is going from a file (hello.txt) to no file at all */
if (this.files && this.files[0]) {
/* Since we can chose more than one file by shift clicking multiple files, here we ensure that we only take the first one set. */
var myFile = this.files[0];
/* FileReader is the Object in the JavaScript standard that has the capabilities to read and get informations about files (content, size, creation date, etc) */
var reader = new FileReader();
/* Here we give the instruction for the FileReader we created, we tell it that when it loads, it should do some stuff. The load event is fired when the FileReader reads a file. In our case this hasn't happened yet, but as soon as it will this function will fire. */
reader.addEventListener("load", function (e) {
/* What we do here is take the result of the fileReader and put it inside our output div to display it to the users. This is where you could do your scrambling and maybe save the result in a variable ? */
output.textContent = e.target.result;
});
/* This is where we tell the FileReader to open and get the content of the file. This will fire the load event and get the function above to execute its code. */
reader.readAsText(myFile);
}
});
</script>
With this I hope you'll be able to understand the first part of this code. Try putting the second part of your code instead of output.textContent and replacing data with e.target.result, that should do what you wish, but I'll let you figure it out by yourself first, comment on this answer if you need further help !
Here's a codepen with working and commented code:
https://codepen.io/MattDirty/pen/eYZVWyK

how can i read with jquery a file csv that has been uploaded with html form?

I am trying to read a csv file with jquery. I have passed the file with input tag of html but i am having some problems to read it. Below the code that i have written.
HTML code:
<div id="insertCSV" class = "formblacktransparent">
<input id="csv" type="file" accept=".csv" class="form-control" placeholder="Insert csv"> </input>
<button type="button" class="log-btn" id="confCsv"> Confirm </button>
</div>
Jquery code:
$("#confCsv").click(function(data){
var input = document.getElementById('csv');
var file = input.files[0];
alert(file[0]);
var fr = new FileReader();
fr.readAsDataURL(data);
alert(fr);
});
I don 't understand if in this way the file has been uploaded and how i can accede to it.
Any ideas? thank you in advance!!
I write below the code that i have used to resolve my problem. I hope it can be useful. Hello!
document.querySelector("#confCsv").addEventListener('click', function() {
if(document.querySelector("#csv").files.length == 0) {
alert('Error : No file selected');
return;
}
// first file selected by user
var file = document.querySelector("#csv").files[0];
// perform validation on file type & size if required
// read the file
var reader = new FileReader();
// file reading started
reader.addEventListener('loadstart', function() {
console.log('File reading started');
});
// file reading finished successfully
reader.addEventListener('load', function(e) {
// contents of file in variable
var text = e.target.result;
var row = text.split('\n');
row.forEach(function(e) {
var datiGiornalieri = e.split(';');
socket.emit('parameterRegistrationFile', {ID: patientID, paramdata: datiGiornalieri[0], parametername: 'alfa',parametervalue: datiGiornalieri[1] });
});
});
reader.readAsText(file);
});

Change name File selected by input type file

I want to change name's file selected by input type=file, but it doesn't work.
This is my code:
$("document").ready(function() {
$('body').on('change', '#FileID', function() {
var name = document.getElementById('FileID');
name.files.item(0).name = Math.floor(Math.random() * 100000);
console.log('Selected file: ' + name.files.item(0).name);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id='FileID' class='class1' type='file' name='Images' value='' />
To change the name of a File object, you need to create a new File instance.
You can create one from a previous File object and it will act a simple wrapper over the data on disk.
The sketchier part is to update the <input type="file"> value to use this new File.
It is now possible through an hack as exposed in this answer of mine:
$('body').on('change', '#FileID', function(evt) {
const newName = Math.floor(Math.random() * 100000);
const input = evt.currentTarget;
const previousFile = input.files[0];
const newFile = new File([previousFile], newName);
// hack to update the selected file
const dT = new DataTransfer();
dT.items.add(newFile);
input.files = dT.files;
console.log('Selected file: ' + input.files.item(0).name);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id='FileID' class='class1' type='file' name='Images' value='' />
However since this part is still mainly an hack, I can't really recommend its use.
So if you don't need to show the updated value in the native input, don't do it. Simply update a custom UI, and use a FormData to upload to your server. The last param of FormData#append(blob, fieldname, filename) will set the filename sent by the browser in the form-data request:
const form = new FormData();
const file = new File(["some data"], "originalname.txt");
form.append("fileField", file, Math.floor(Math.random() * 100000));
console.log("original file's name: ", file.name);
new Response(form).text()
.then((content) => console.log("formdata content: ", content));
So you should not need the aforementioned hacks at all.
For anyone ending here trying to get rid of the file's name, try converting it to base64. this way it won't have the name attached to it and you could upload it how you want. I will leave a code example using reactJS for this.
1: Here is the input file type calling the onChange event with our function:
<input onChange={this.handleBackgroundImagePreview} type="file" accept="image/png,image/gif,image/jpeg"></input>
2: Then convert that image to base64
handleBackgroundImagePreview = (e) =>{
// Retrieves the selected Image or file
const file = e.target.files[0]
//Calling async file reader with a callback
let fileBase64 = '';
this.getBase64(file, (result) => {
fileBase64 = result;
console.log(fileBase64)
//In here you could upload to the server the base 64 data as you want
});
}
getBase64(file, cb) {
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
cb(reader.result)
};
reader.onerror = function (error) {
console.log('Error: ', error);
};
}

How to open select file dialog via js?

$('#id').click();
It doesn't work on Chrome 26 on Mac OS.
The problem actually is creation "upload" widget that can be integrated in a form.
Widget will consists of two parts. The first part is div with initiator button and error/success messages.
I think the way is put another form as the second part with file input and submit file into the iframe. After submition we fill hidden field in first part in main form or show errors in the same.
Easy way is adding file-form into main-form, but it's prohibited.
JS only - no need for jquery
Simply create an input element and trigger the click.
var input = document.createElement('input');
input.type = 'file';
input.click();
This is the most basic, pop a select-a-file dialog, but its no use for anything without handling the selected file...
Handling the files
Adding an onchange event to the newly created input would allow us to do stuff once the user has selected the file.
var input = document.createElement('input');
input.type = 'file';
input.onchange = e => {
var file = e.target.files[0];
}
input.click();
At the moment we have the file variable storing various information :
file.name // the file's name including extension
file.size // the size in bytes
file.type // file type ex. 'application/pdf'
Great!
But, what if we need the content of the file?
In order to get to the actual content of the file, for various reasons. place an image, load into canvas, create a window with Base64 data url, etc. we would need to use the FileReader API
We would create an instance of the FileReader, and load our user selected file reference to it.
var input = document.createElement('input');
input.type = 'file';
input.onchange = e => {
// getting a hold of the file reference
var file = e.target.files[0];
// setting up the reader
var reader = new FileReader();
reader.readAsText(file,'UTF-8');
// here we tell the reader what to do when it's done reading...
reader.onload = readerEvent => {
var content = readerEvent.target.result; // this is the content!
console.log( content );
}
}
input.click();
Trying pasting the above code into your devtool's console window, it should produce a select-a-file dialog, after selecting the file, the console should now print the contents of the file.
Example - "Stackoverflow's new background image!"
Let's try to create a file select dialog to change stackoverflows background image to something more spicy...
var input = document.createElement('input');
input.type = 'file';
input.onchange = e => {
// getting a hold of the file reference
var file = e.target.files[0];
// setting up the reader
var reader = new FileReader();
reader.readAsDataURL(file); // this is reading as data url
// here we tell the reader what to do when it's done reading...
reader.onload = readerEvent => {
var content = readerEvent.target.result; // this is the content!
document.querySelector('#content').style.backgroundImage = 'url('+ content +')';
}
}
input.click();
open devtools, and paste the above code into console window, this should pop a select-a-file dialog, upon selecting an image, stackoverflows content box background should change to the image selected.
Using jQuery
I would create a button and an invisible input like so:
<button id="button">Open</button>
<input id="file-input" type="file" name="name" style="display: none;" />
and add some jQuery to trigger it:
$('#button').on('click', function() {
$('#file-input').trigger('click');
});
Using Vanilla JS
Same idea, without jQuery (credits to #Pascale):
<button onclick="document.getElementById('file-input').click();">Open</button>
<input id="file-input" type="file" name="name" style="display: none;" />
Ready-to-use function (using Promise)
/**
* Select file(s).
* #param {String} contentType The content type of files you wish to select. For instance, use "image/*" to select all types of images.
* #param {Boolean} multiple Indicates if the user can select multiple files.
* #returns {Promise<File|File[]>} A promise of a file or array of files in case the multiple parameter is true.
*/
function selectFile(contentType, multiple){
return new Promise(resolve => {
let input = document.createElement('input');
input.type = 'file';
input.multiple = multiple;
input.accept = contentType;
input.onchange = () => {
let files = Array.from(input.files);
if (multiple)
resolve(files);
else
resolve(files[0]);
};
input.click();
});
}
Try it here
// Content wrapper element
let contentElement = document.getElementById("content");
// Button callback
async function onButtonClicked(){
let files = await selectFile("image/*", true);
contentElement.innerHTML = files.map(file => `<img src="${URL.createObjectURL(file)}" style="width: 100px; height: 100px;">`).join('');
}
// ---- function definition ----
function selectFile (contentType, multiple){
return new Promise(resolve => {
let input = document.createElement('input');
input.type = 'file';
input.multiple = multiple;
input.accept = contentType;
input.onchange = _ => {
let files = Array.from(input.files);
if (multiple)
resolve(files);
else
resolve(files[0]);
};
input.click();
});
}
<button onclick="onButtonClicked()">Select images</button>
<div id="content"></div>
For the sake of completeness, Ron van der Heijden's solution in pure JavaScript:
<button onclick="document.querySelector('.inputFile').click();">Select File ...</button>
<input class="inputFile" type="file" style="display: none;">
In HTML only:
<label>
<input type="file" name="input-name" style="display: none;" />
<span>Select file</span>
</label>
Check this fiddle with the code above.
To expand on the answer from 'levi' and to show how to get the response from the upload so you can process the file upload:
selectFile(event) {
event.preventDefault();
file_input = document.createElement('input');
file_input.addEventListener("change", uploadFile, false);
file_input.type = 'file';
file_input.click();
},
uploadFile() {
let dataArray = new FormData();
dataArray.append('file', file_input.files[0]);
// Obviously, you can substitute with JQuery or whatever
axios.post('/your_super_special_url', dataArray).then(function() {
//
});
}
function promptFile(contentType, multiple) {
var input = document.createElement("input");
input.type = "file";
input.multiple = multiple;
input.accept = contentType;
return new Promise(function(resolve) {
document.activeElement.onfocus = function() {
document.activeElement.onfocus = null;
setTimeout(resolve, 500);
};
input.onchange = function() {
var files = Array.from(input.files);
if (multiple)
return resolve(files);
resolve(files[0]);
};
input.click();
});
}
function promptFilename() {
promptFile().then(function(file) {
document.querySelector("span").innerText = file && file.name || "no file selected";
});
}
<button onclick="promptFilename()">Open</button>
<span></span>
First Declare a variable to store filenames (to use them later):
var myfiles = [];
Open File Dialog
$('#browseBtn').click(function() {
$('<input type="file" multiple>').on('change', function () {
myfiles = this.files; //save selected files to the array
console.log(myfiles); //show them on console
}).click();
});
i'm posting it, so it may help someone because there are no clear instructions on the internet to how to store filenames into an array!
With jquery library
<button onclick="$('.inputFile').click();">Select File ...</button>
<input class="inputFile" type="file" style="display: none;">
This problem puzzled me. Adding addeventlistener invoked the event which was something I didn't want. If you're interest is in a simple chooser, events aren't required. the input/file dialog will return from the separate window to the caller with the selected filename (if you look at the element in a debugger the "files" object also carries some other attributes. Thank you user4602228 for pointing the way...
Simple in/out file selector shown below >>>
function loadsettings()
//
// use web page dialog to get user settings file
//
{
var setload=parent.settings.document.createElement("input");
setload.type="file";
setload.click();
settings(*setload.files[0]*,false,false); //these are custom parameters
}
return;

Categories