Read JSON from from HTML file input - javascript

If I have an input:
<input type="file" id="upload" onchange="getFile(this)">
And my user will upload a JSON file (as plaintext, so I will have to use JSON.parse()), how can I take this file and actually get the data via getFile()
In getFile(element), I've tried using element.files[0] but that doesn't seem to contain the actual data. I've also looked here, here, and here, but none of these solve my problem. This resource on MDN seems promising, but I don't really get it.
I would like a solution involving either URL.createObjectURL() or FileReader().
Also, before anyone posts this in the comments, I do understand that these solutions do not work on all browsers, and I would like to do this from the frontend.

You could take advantage of the Response constructor and call .json() on any blob/file.
function getFile (elm) {
new Response(elm.files[0]).json().then(json => {
console.log(json)
}, err => {
// not json
})
}
Alternative method using the new read methods on blob.prototype[...]
new Blob(['1']).text().then(JSON.parse).then(console.log)
I guess for larger files response.json might be faster/better since it can parse the content in background and not block the main UI unlike JSON.parse

I think you need this api:
FileReader Api From MDN
JSON#parse()
View In Stackblitz
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Read Text</title>
<style>
div {
margin-top: 30px;
border: solid 1px black;
padding: 5px;
}
</style>
<script>
function processFiles(files) {
var file = files[0];
var message = document.getElementById("message");
message.innerHTML = "File Name:" + file.name + "<br>";
message.innerHTML += "File Size:" + file.size + "<br>";
message.innerHTML += "File Type:" + file.type + "<br>";
var reader = new FileReader();
reader.onload = function (e) {
var output = document.getElementById("fileOutput");
// parse string to json
output.textContent = JSON.parse(e.target.result);
};
reader.readAsText(file);
}
</script>
</head>
<body>
<input id="fileInput" type="file" size="50" onchange="processFiles(this.files)">
<div id="message"></div>
<div id="fileOutput"></div>
</body>
</html>

Related

Automatically load csv/txt file from local drive into html page as table Javascript

I found a lot of good suggestions on how to load a csv/txt file into a html page into a table, but none of the solutions are working for me. Here is the code I am working with. I have both files located in my C: drive and basically would like to load this csv/txt file and show it on as a table in index.html. Thanks so much!
data.txt
heading1,heading2,heading3,heading4,heading5
value1_1,value2_1,value3_1,value4_1,value5_1
value1_2,value2_2,value3_2,value4_2,value5_2
index.html
<!DOCTYPE html>
<!-- saved from url=(0014)about:internet -->
<html lang="en">
<html>
<head>
<title>Test</title>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type: "GET",
url: "data.txt",
dataType: "text",
success: function(data) {processData(data);}
});
});
function processData(allText) {
var allTextLines = allText.split(/\r\n|\n/);
var headers = allTextLines[0].split(',');
var lines = [];
for (var i=1; i<allTextLines.length; i++) {
var data = allTextLines[i].split(',');
if (data.length == headers.length) {
var tarr = [];
for (var j=0; j<headers.length; j++) {
tarr.push(headers[j]+":"+data[j]);
}
lines.push(tarr);
}
}
\\ alert(lines);
}
</script>
</body>
</html>
You can't access local files with JS. That would be serious security vulnerability, because you could send a malicious webpage to a user, which would download their files and send them to someone. As midrizi mentioned in the comments, you'll need a server to download files from there.
As others have noted, you can't automatically read a local file into the browser.
But you can prompt the user to select a file, using the <input type="file"> element.
Once a file has been selected via that input, it can be read via JavaScript.
<label for="file">Select a Text File:</label><br />
<input id="file" type="file" /><br/>
<button onclick="readFile()">Read File</button><br/>
let input = document.getElementById('file');
let contents = document.getElementById('contents');
function readFile () {
let file = input.files[0];
const reader = new FileReader();
reader.onload = function (evt) {
console.log('reader.onload');
contents.innerHTML = String(evt.target.result);
};
reader.readAsText(file);
}
If you can modify the data.txt a bit you can just load it as another script file without need for a server.
Change data.txt to this
var data = `heading1,heading2,heading3,heading4,heading5
value1_1,value2_1,value3_1,value4_1,value5_1
value1_2,value2_2,value3_2,value4_2,value5_2`
And load it as a javascript file before your actual script
<script type="text/javascript" src="data.txt"></script>
Then you can use the variable data which holds your file content without any ajax call.
There is no way you can retrieve a local file if you don't serve it, as pointed out in the comments to your question.
There are approaches you can take to that, though. If you can't serve it by any means, you could create a GitHub repo and upload your file there. Then you can use the link to your raw file:
And you can also take steps to automate that, but it should be easy enough committing your file locally whenever you update it and push it to GitHub. Just in case you're not familiar with Git and GitHub, here's a handy ref.
A word of caution: unless you have total control over the characters that you include in your CSV, parsing them by naively splitting commas like that might result in ugly stuff if the values within contain commas themselves. Some CSV files also come with extra stuff in the beginning of the file (like the sep indicator in the first row, which defines what character to interpret as separator). You may completely ignore these warnings if you're producing the CSV yourself.
Also I noticed your function does not take care of building the actual table, so I changed it so it does. I also used Fetch API to retrieve the data:
<!DOCTYPE html>
<!-- saved from url=(0014)about:internet -->
<html lang="en">
<html>
<head>
<title>Test</title>
</head>
<body>
<script type="text/javascript">
function processData(csv) {
let data = csv.split(/\r\n|\n/).map(v => v.split(','));
let headers = data.shift();
let table = document.createElement('table');
let thead = document.createElement('thead');
table.appendChild(thead);
thead.innerHTML = '<tr><th>' + headers.join('</th><th>') + '</th></tr>';
let tbody = document.createElement('tbody');
table.appendChild(tbody);
for (let row of data) {
tbody.innerHTML += '<tr><td>' + row.join('</td><td>') + '</td></tr>';
}
document.body.appendChild(table);
}
// I uploaded the CSV to a personal repo for this example,
// but you CAN use a local file as long as you *serve* it
fetch("https://raw.githubusercontent.com/gyohza/test/master/so/data.txt")
.then(res => res.text())
.then(text => processData(text));
</script>
</body>
</html>

have to encode by HTML link with base64

It is my first post and hope it won't be already solved previously.
I'm using a call center software and also using Salesforce lightning.
When a caller calls, I would like to check in my CRM if it is a customer or not.
It was possible easily with the basic version of Salesforce but is not anymore because the link is coded with base64.
Please, read this post for more explanation : https://tomsmalara.blogspot.com/2019/01/create-lightning-component-that.html
So, I have to create a HTML page for collecting the caller phone number and compose + encrypt the Salesforce link and open the link encrypted.
<!DOCTYPE html>
<html>
<head>
<title>Waiting a call ...</title>
<style>
body {text-align: center;}
</style>
</head>
<body>
<form name="form1" onsubmit="event.preventDefault();return displayResult();">
<label for="name">Phone number:</label>
<input type="text" id="PhoneNumber" name="PhoneNumber" size="10">
<div id="myEncoding"></div>
</form>
<script>
function b64EncodeUnicode(PhoneNumber) {
// first we use encodeURIComponent to get percent-encoded UTF-8,
// then we convert the percent encodings into raw bytes which
// can be fed into btoa.
var Mytxt = '{"componentDef":"forceSearch:search","attributes":{"term":"'+PhoneNumber+'","scopeMap":{"resultsCmp":"forceSearch:resultsTopResults","label":"Top Results","type":"TOP_RESULTS","cacheable":"Y","id":"TOP_RESULTS","labelPlural":"Top Results"},"context":{"disableSpellCorrection":false,"SEARCH_ACTIVITY":{"term":1234567890}}},"state":{}}';
return btoa(encodeURIComponent(Mytxt).replace(/%([0-9A-F]{2})/g,
function toSolidBytes(match, p1) {
var MyResult = String.fromCharCode('0x' + p1);
return MyResult;
}));
}
function displayResult() {
var result = b64EncodeUnicode(PhoneNumber);
document.getElementById('myEncoding').innerHTML = result;
return false;
window.open("https://mycompany.lightning.force.com/one/one.app#" +result,,,true)
}
</script>
</body>
</html>
Something is wrong and tried different things without result.
I will really appreciate if someone can find what is wrong and explain it to me
Thank you in advance
PLease find the solution I found to remove the input steps ...
<!DOCTYPE html>
<html>
<head>
<title>Waiting a call ...</title>
<style>
body {text-align: center;}
</style>
</head>
<body onload=acceptParam()>
Waiting a call ...
<script>
function acceptParam(){
var hashParams = window.location.href.substr(1).split('?'); // substr(1) to remove the `#`
hashParams = hashParams[1].split('&');
var p = hashParams[0].split('=');
//document.getElementById('PhoneNumber').value = p[1] // Pour info
var stringToEncode = '{"componentDef":"forceSearch:searchPage","attributes":{"term":"'+p[1]+'","scopeMap":{"type":"TOP_RESULTS"},"context":{"disableSpellCorrection":false,"disableIntentQuery":false,"permsAndPrefs":{"SearchUi.searchUIPilotFeatureEnabled":false,"SearchExperience.LeftNavEnhancementEnabled":true,"Search.crossObjectsAutoSuggestEnabled":true,"SearchResultsLVM.lvmEnabledForSearchResultsOn":true,"MySearch.userCanHaveMySearchBestResult":false,"SearchResultsLVM.lvmEnabledForTopResults":false,"OrgPermissions.UnionAppNavSmartScope":false,"SearchUi.feedbackComponentEnabled":false,"SearchExperience.TopResultsSingleSOSLEnabled":false,"OrgPreferences.ChatterEnabled":true,"Search.maskSearchInfoInLogs":false,"SearchUi.orgHasAccessToSearchTermHistory":false,"SearchUi.searchUIInteractionLoggingEnabled":false,"MySearch.userCanHaveMySearch":false},"searchDialogSessionId":"bdded2dc-91d1-3b3e-11d7-ff339bce1727","searchSource":"INPUT_DESKTOP"},"groupId":"DEFAULT"},"state":{}}'
var encoded = window.btoa(stringToEncode);
//var output = "Encoded String : " + encoded;
//document.getElementById("myEncoding").innerHTML = "Original String: " + p[1] + "<br>" + output;
window.location.assign("https://mycompany.lightning.force.com/lightning/one/one.app?source=alohaHeader#"+encoded);
}
</script>
</body>
</html>
PLease, can you say me what do you think about it ? Maybe we can be more efficient ?

Getting text from file using FileReader on Load

So, I've been working on a page that uses only local files (server is not an option, unfortunately. Not even a localhost. The struggle is real.) and I've come to a situation where I need to grab text from a .csv file and populate it to the page. I have this bit of code that works, but I need to have a file set within the function when a button is pressed. Looking up the file manually isn't an option (to visualize what I'm doing, I'm making a mock database file in the most annoying way possible (because I have to, not because I want to)).
In the page I would have something like:
<button id="myButton" onclick="getText()"></button>
<script>
var myFile = "dataset.csv";
...
</script>
The following bit of code works (in regards to having it pull the data from the csv file), but, as I said, I need to pull the text from the file when a button is pressed and just have the file name set in the script, not pulling it up manually.
<!DOCTYPE html>
<html>
<body>
<input type="file" id="fileinput" />
<div id="outputdiv"></div>
<script type="text/javascript">
function readSingleFile(evt) {
var f = evt.target.files[0];
if (f) {
var r = new FileReader();
r.onload = function(e) {
var contents = e.target.result;
var splited = contents.split(/\r\n|\n|\r|,/g);
for (i=0; i<splited.length; i++){
document.getElementById("outputdiv").innerHTML = document.getElementById("outputdiv").innerHTML + splited[i] + "<br>";
}
}
r.readAsText(f);
} else {
alert("Failed to load file");
}
}
document.getElementById('fileinput').addEventListener('change', readSingleFile, false);
</script>
</body>
</html>
From what I can tell from the API, I would need to set the file attributes to a blob in order to pass it to FileReader. How I can do this without using an input box, I have no idea. There's also a 50% chance that I am completely wrong about this since I obviously don't know how to get this done.
If someone could show me how to achieve this with regards to what I'm looking for, it would be very much appreciated. I'm absolutely stumped.
Thank you.
Note: CORS restrictons will prevent this from working in most browsers. You can use FireFox Developer Edition, which disables CORS validation.
You can use an XMLHttpRequest to load a local file:
<!DOCTYPE html>
<html>
<body>
<button onclick="readSingleFile()">Click Me</button>
<div id="outputdiv"></div>
<script type="text/javascript">
function readSingleFile() {
let xhr = new XMLHttpRequest();
let url = "relative/path/to/file.txt;
if (!url) return;
xhr.onload = dataLoaded;
xhr.onerror = _ => "There was an error loading the file.";
xhr.overrideMimeType("text/plain");
xhr.open("GET",url);
xhr.send();
}
function dataLoaded(e){
var contents = e.target.responseText;
var splited = contents.split(/\r\n|\n|\r|,/g);
for (i=0; i<splited.length; i++){
document.getElementById("outputdiv").innerHTML = document.getElementById("outputdiv").innerHTML + splited[i] + "<br>";
}
</script>
</body>
</html>

javascript auto-upload or reading a file form a local dir

I tried to read a local file. I've got a solution for MSIE.
But chorme and firefox are a little bit more restrict for such manipulations.
So I tried to use the FileReader but it seems taht it is not possible to read form a local dirve.
After some tests I've got this idea.
I want to 'auto-upload' the file without any dialog.
<!doctype html>
<html>
<script>
function handle_files(files) {
for (i = 0; i < files.length; i++) {
file = files[i]
console.log(file)
var reader = new FileReader()
reader.onload = function(e) {
console.log(e.target.result)
}
reader.onerror = function(stuff) {
console.log("error", stuff)
console.log (stuff.getMessage())
}
reader.readAsText(file) //readAsdataURL
}
}
handle_files(document.getElementById("input").value);
</script>
<body>
FileReader that works!
<input type="file" multiple onmouseover="handle_files(this.files)" id="input" value="K:\\somewhere\\over\\the\\rainbow\\c_comments.txt">
</body>
</html>
My question is now: How to manage a quite upload ?
Maybe somebody has a nice idea.
Thanks
br
Markus

get the data of uploaded file in javascript

I want to upload a csv file and process the data inside that file. What is the best method to do so? I prefer not to use php script. I did the following steps. But this method only returns the file name instead of file path.So i didnt get the desired output.
<form id='importPfForm'>
<input type='file' name='datafile' size='20'>
<input type='button' value='IMPORT' onclick='importPortfolioFunction()'/>
</form>
function importPortfolioFunction( arg ) {
var f = document.getElementById( 'importPfForm' );
var fileName= f.datafile.value;
}
So how can i get the data inside that file?
The example below is based on the html5rocks solution. It uses the browser's FileReader() function. Newer browsers only.
See http://www.html5rocks.com/en/tutorials/file/dndfiles/#toc-reading-files
In this example, the user selects an HTML file. It is displayed in the <textarea>.
<form enctype="multipart/form-data">
<input id="upload" type=file accept="text/html" name="files[]" size=30>
</form>
<textarea class="form-control" rows=35 cols=120 id="ms_word_filtered_html"></textarea>
<script>
function handleFileSelect(evt) {
let files = evt.target.files; // FileList object
// use the 1st file from the list
let f = files[0];
let reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
jQuery( '#ms_word_filtered_html' ).val( e.target.result );
};
})(f);
// Read in the image file as a data URL.
reader.readAsText(f);
}
document.getElementById('upload').addEventListener('change', handleFileSelect, false);
</script>
you can use the new HTML 5 file api to read file contents
https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications
but this won't work on every browser so you probably need a server side fallback.
The example below shows the basic usage of the FileReader to read the contents of an uploaded file. Here is a working Plunker of this example.
function init() {
document.getElementById('fileInput').addEventListener('change', handleFileSelect, false);
}
function handleFileSelect(event) {
const reader = new FileReader()
reader.onload = handleFileLoad;
reader.readAsText(event.target.files[0])
}
function handleFileLoad(event) {
console.log(event);
document.getElementById('fileContent').textContent = event.target.result;
}
<!DOCTYPE html>
<html>
<head>
<script src="script.js"></script>
</head>
<body onload="init()">
<input id="fileInput" type="file" name="file" />
<pre id="fileContent"></pre>
</body>
</html>
There exist some new tools on the blob itself that you can use to read the files content as a promise that makes you not have to use the legacy FileReader
// What you need to listen for on the file input
function fileInputChange (evt) {
for (let file of evt.target.files) {
read(file)
}
}
async function read(file) {
// Read the file as text
console.log(await file.text())
// Read the file as ArrayBuffer to handle binary data
console.log(new Uint8Array(await file.arrayBuffer()))
// Abuse response to read json data
console.log(await new Response(file).json())
// Read large data chunk by chunk
console.log(file.stream())
}
read(new File(['{"data": "abc"}'], 'sample.json'))
Try This
document.getElementById('myfile').addEventListener('change', function() {
var GetFile = new FileReader();
GetFile .onload=function(){
// DO Somthing
document.getElementById('output').value= GetFile.result;
}
GetFile.readAsText(this.files[0]);
})
<input type="file" id="myfile">
<textarea id="output" rows="4" cols="50"></textarea>
FileReaderJS can read the files for you. You get the file content inside onLoad(e) event handler as e.target.result.

Categories