Load, manipulate and save text file with javascript? - javascript

I've got a text file and want to do some find and replace operations to it inside the browser. Unfortunately my coding experience is just really elementary and complete tutorials about building web apps are far too much input at the moment.
Basically I want to upload the file into the browser, then let javascript do the find-and-replace-thing and finally want to download the changed file again.
I've already read about the HTML5 File API and was actually able to load the text file into the browser. But that is where I'm getting lost. In order to split problems up into smaller ones I thought a good next step would be to download the uploaded file again and finally learn how to put the find-and-replace action in between. But I really don't know how to go further and would appreciate any help.
Thanks so far. Benny
document.getElementById('input-file')
.addEventListener('change', getFile)
function getFile(event) {
const input = event.target
if ('files' in input && input.files.length > 0) {
placeFileContent(
document.getElementById('content-target'),
input.files[0])
}
}
function placeFileContent(target, file) {
readFileContent(file).then(content => {
target.value = content
}).catch(error => console.log(error))
}
function readFileContent(file) {
const reader = new FileReader()
return new Promise((resolve, reject) => {
reader.onload = event => resolve(event.target.result)
reader.onerror = error => reject(error)
reader.readAsText(file, "windows-1252")
})
}
<html>
<head>
<meta content="text/html; charset=ANSI" http-equiv="content-type">
<title>Text file manipulator</title>
</head>
<body>
<h1>Text file manipulator</h1>
<p>
<input type="file" id="input-file">
</p>
<p>
<textarea id="content-target" style="width:440px;height:400px;"></textarea>
</p>
</body>
</html>
screenshot of text file uploader

You can add a button and call a function in your JavaScript. Something like
<button onclick="downloadText()">Download</button>
Being the function
function downloadText(){
var content = document.getElementById('content-target').value;
var dl = document.createElement('a');
dl.setAttribute('href', 'data:text/csv;charset=utf-8,' +
encodeURIComponent(content));
dl.setAttribute('download', 'text.txt');
dl.click();
}
Inside the function you should be able to do all the modifications you want. If you give more details, I can help you with the replace section of it, but it should be something like the following:
content.replace(regex, substitute);
More information here
Working CodePen

Related

Read a file in browser in JS [duplicate]

I have this code and for a file to be converted into base64 I have to click on Choose file and then select it. I want to hardcode the file name so it is converted to base64 on page load.
JavaScript:
var handleFileSelect = function(evt) {
var files = evt.target.files;
var file = files[0];
if (files && file) {
var reader = new FileReader();
reader.onload = function(readerEvt) {
var binaryString = readerEvt.target.result;
document.getElementById("base64textarea").value = btoa(binaryString);
};
reader.readAsBinaryString(file);
}
if (window.File && window.FileReader
&& window.FileList && window.Blob) {
document.getElementById('filePicker')
.addEventListener('change', handleFileSelect, false);
} else {
alert('The File APIs are not fully supported in this browser.');
}
};
HTML:
<div>
<div>
<label for="filePicker">Choose or drag a file:</label><br/>
<input type="file" id="filePicker">
</div>
</br>
<div>
<h1>Base64 encoded version</h1>
<textarea id="base64textarea"
placeholder="Base64 will appear here"
cols="50" rows="15">
</textarea>
</div>
</div>
EDIT: Thank you for your answers, they were really helpful.
You simply can't do what you are trying to do. Setting the path for an input element through Javascript is not possible, as a security measure. Please check here: How to resolve the C:\fakepath?
You can launch chromium, chrome browser with --allow-file-access-from-files flag set, use fetch() of XMLHttpRequest() to request file from local filesystem.
fetch("file:///path/to/file")
.then(response => response.arrayBuffer())
.then(ab => {
// do stuff with `ArrayBuffer` representation of file
})
.catch(err => console.log(err));
See also Read local XML with JS
The File API is not good to read local files without user intervention, but the Web API is (of course, within its limitations, like not working in Chromium without explicitly enabling access to local files and whatnot).
So, here it is, in case someone else needs a working example of how to load a local file without user intervention, i.e., without requiring user to push any INPUT button (but still giving the user a means to abort the loading).
Parameters: file name, request type (text, blob etc.), MIME type and a function to be executed after the file is completely loaded. File is loaded in variable X, which is then used to populated an object.
To abort the file reading, just click on the progress bar (also, just an example, not essential for the program to work). Because it is asynchronous, as many files as wanted may be read at the same time (one progress bar is created for each file).
I only created examples for a text file and a video, but it should work with any kind of files.
<html>
<head>
<meta charset="utf-8"/>
<script type="text/javascript">
function LoadFile(FileName,RespType,FileType,RunMe)
{ var AJAXFileReader=new XMLHttpRequest();
// Creates new progress bar.
var ProgressBar=CreateSVGProgBar("ProgressBars");
AJAXFileReader.addEventListener("progress",
function FRProgress(AJAXFREvt)
{ // Calculate progress.
var X=-1;
if (AJAXFREvt.lengthComputable)
X=Math.trunc(AJAXFREvt.loaded/AJAXFREvt.total*100);
ShowProgressBar(ProgressBar,FileName,X);
});
AJAXFileReader.addEventListener("error",function FRFailed()
{ // This will be executed if an error occurs.
console.log("Error:",this.status);
});
AJAXFileReader.addEventListener("timeout",function FRTimeOut()
{ // This will be executed if the reading times out.
console.log("File reading timed out!");
});
AJAXFileReader.addEventListener("abort",
function FRCancel()
{ // This will confirm reading was aborted.
console.log("File reading cancelled by user!");
});
ProgressBar.addEventListener("click",
function KillMe()
{ // Adds an abort command to the object.
console.log(AJAXFileReader.readyState);
if (AJAXFileReader.readyState!=4)
{ console.log("Aborting file reading...");
AJAXFileReader.abort();
}
ProgressBar.removeEventListener("click",KillMe);
},
false);
AJAXFileReader.addEventListener("load",
function Finished()
{ // When reading is finished, send data to external function.
if ((this.readyState==4)&&(this.status==200))
{ ShowProgressBar(ProgressBar,FileName,100);
RunMe(this.response);
//ProgressBar.click();
}
},
false);
AJAXFileReader.open("GET",FileName,true);
AJAXFileReader.overrideMimeType(FileType);
AJAXFileReader.responseType=RespType;
AJAXFileReader.timeout=10000; // Setting time-out to 10 s.
AJAXFileReader.send();
}
function CreateSVGProgBar(AnchorId)
{ // Creates new SVG progress bar.
var Parent=document.getElementById(AnchorId);
var NewSVG=document.createElementNS("http://www.w3.org/2000/svg","svg");
NewSVG.setAttribute("viewBox","0 0 102 22");
NewSVG.setAttribute("width","102");
NewSVG.setAttribute("height","22");
Parent.appendChild(NewSVG);
return NewSVG;
}
function ShowProgressBar(E,N,X)
{ // Show progress bar.
var P=X<0?"???":X+"%";
E.innerHTML="<text x=\"50\" y=\"16\" font-size=\"12\" fill=\"black\" stroke=\"black\" text-anchor=\"middle\">"+N+"</text><rect x=\"1\" y=\"1\" width=\""+X+"\" height=\"20\" fill=\""+(X<100?"#FF0000":"#0000FF")+"\" stroke=\"none\"/><rect x=\"1\" y=\"1\" width=\"100\" height=\"20\" fill=\"none\" stroke=\"black\" stroke-width=\"1\"/><text x=\""+X/2+"\" y=\"16\" font-size=\"12\" fill=\"black\" stroke=\"black\" text-anchor=\"middle\">"+P+"</text>";
}
function TracerOn(X)
{ // This will be executed after the file is completely loaded.
document.getElementById("Tron").innerHTML=X;
}
function PlayIt(X)
{ // This will be executed after the file is completely loaded.
var blob_uri=URL.createObjectURL(X);
document.getElementById("MagicalBox").appendChild(document.createElement("source")).src=blob_uri;
}
function Startup()
{ // Run after the Page is loaded.
LoadFile("example.txt","text","text/plain;charset=utf-8",TracerOn);
LoadFile("video.mp4","blob","video/mp4",PlayIt);
}
</script>
</head>
<body onload="Startup()">
<div id="ProgressBars"></div>
<div id="Tron">Text...</div>
<video id="MagicalBox" width="400" controls>Video...</video>
</body>
</html>

Asp.net Project - Javascript button is clickable but not carrying out the function

I've been trying to integrate an api into a project that I have been working on with some friends but I'm having difficulty with getting the "ok" button to actually execute the function. It's supposed to allow you to upload a photo, click ok, and then it returns data about the plant. The "choose files button works, but the ok button doesn't.
Since the API sample was already created I tested it in a separate solution and was able to get it to work which leads me to believe that I've made a mistake in the code somewhere else or maybe there's something blocking the program from talking to API's web address. But for some reason it doesn't work within the project that I'm trying to integrate it into. (ASP.NET razor page).
I've also tried making a new button and moving the javascript tag into the header and other spots but that didn't work either, and I've run out of ideas to try. I have omitted the api key itself below for the sake of privacy. I'd really appreciate any help on the subject!
#{
ViewData["Title"] = "Identify a Plant";
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<form>
<input type="file" multiple />
<!--<button type="button">OK</button> -->
<button type="button">OK</button>
</form>
<script type="text/javascript">
document.querySelector('button').onclick = function sendIdentification() {
const files = [...document.querySelector('input[type=file]').files];
const promises = files.map((file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
const res = event.target.result;
console.log(res);
resolve(res);
}
reader.readAsDataURL(file)
})
})
Promise.all(promises).then((base64files) => {
console.log(base64files)
const data = {
api_key: "Die8ewFGvpw5JrRTuOEjgGR10uL--",
images: base64files,
modifiers: ["crops_fast", "similar_images"],
plant_language: "en",
plant_details: ["common_names",
"url",
"name_authority",
"wiki_description",
"taxonomy",
"synonyms"]
};
fetch('https://api.plant.id/v2/identify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
})
};
</script>
</body>
</html>
I think you are better off to give the button a "ID" and you don't.
and I never really did like this idea of "selecting" some button and then hoping we can attached a click event to that button. So, I always preferred that you have a button. You place a button. You specify a click event for that button. You have to really struggle to figure out which button that selector going to pick up - which one does it like?
And then when you click on that button, the code or function runs. It just a lot easier to follow.
So, your button thus is this:
<form id="form1" runat="server">
<div>
<br />
<input id="myfiles" type="file" multiple="multiple" />
<!--<button type="button">OK</button> -->
<button id="MyButton" type="button" onclick="sendIdentification()" >OK</button>
</div>
</form>
<script type="text/javascript">
function sendIdentification() {
alert('start');
const files = [...document.querySelector('input[type=file]').files];
etc.
The problem is that selector for the click event is subject to the order of the controls and things on the page - might not be picked up correct.
So, just drop in a button. State what that button supposed to do on some click event, and this should help here.
With the querySelector method you add the onClick event on a first button within the document. Since the _Layout.cshtml is rendered first, my first assumption is that you have a button in that view? What about giving an id to the button and adding the onClick event like this:
document.getElementById("myButton").onclick = function sendIdentification() {
//the code
};

Read a .txt file and output him in <p> HTML (with JS)

I have tried a lot of possibilities, but most of them don't work or require modules, but I don't know how to do this in vanilla javascript.. I really need some help.. Thanks. (Sorry for my bad English, I'm french)
My script : (don't really work, just read)
<script type="text/javascript">
var fso, ts, s;
fso = new ActiveXObject("Scripting.FileSystemObject");
f1 = fso.OpenTextFile("pub.txt", 1);
s = ts.ReadLine();
</script>
Reading a text file:
fetch('file.txt')
.then(response => response.text())
.then(text => console.log(text))
// outputs the content of the text file
Using Jquery:
$("#div7").load("ajax.txt");
Try this out!
<input type="file" onchange="readFile(this)" />
<script>
function readFile(input) {
let file = input.files[0];
let reader = new FileReader();
reader.readAsText(file);
reader.onload = function () {
document.getElementById("app").innerHTML = `<p>${reader.result}</p>`;
};
reader.onerror = function () {
console.log(reader.error);
};
}
</script>
document.querySelector("input[type='file']").addEventListener("change", function(){
if(this.files[0]){
this.files[0].text()
.then(val => {
document.querySelector("p").textContent = val;
})
}
})
<label>Pick One Text File</label><br/>
<input type="file" accept="text/plain" multiple="false"> <br/>
<label>File Will Show up here in the text box</label><br/><br/>
<p></p>
Edit: a working example here
https://codepen.io/engeslamadell/pen/WNrVPeG
did you tried this
<script type="text/javascript">
//this is the input with type file
document.getElementById('inputfile')
.addEventListener('change', function() {
var fr=new FileReader();
fr.onload=function(){
document.getElementById('output')
.textContent=fr.result;
}
fr.readAsText(this.files[0]);
})
</script>
you also have these FileReader methods
FileReader.readAsArrayBuffer(): Reads the contents of the specified input file. The result attribute contains an ArrayBuffer representing the file’s data.
FileReader.readAsBinaryString(): Reads the contents of the specified input file. The result attribute contains the raw binary data from the file as a string.
FileReader.readAsDataURL(): Reads the contents of the specified input file. The result attribute contains a URL representing the file’s data.
FileReader.readAsText(): Reads the contents of the specified input file. The result attribute contains the contents of the file as a text string. This method can take encoding version as the second argument(if required). The default encoding is UTF-8.
source: https://www.geeksforgeeks.org/how-to-read-a-local-text-file-using-javascript/

Read local file in javascript [duplicate]

I have this code and for a file to be converted into base64 I have to click on Choose file and then select it. I want to hardcode the file name so it is converted to base64 on page load.
JavaScript:
var handleFileSelect = function(evt) {
var files = evt.target.files;
var file = files[0];
if (files && file) {
var reader = new FileReader();
reader.onload = function(readerEvt) {
var binaryString = readerEvt.target.result;
document.getElementById("base64textarea").value = btoa(binaryString);
};
reader.readAsBinaryString(file);
}
if (window.File && window.FileReader
&& window.FileList && window.Blob) {
document.getElementById('filePicker')
.addEventListener('change', handleFileSelect, false);
} else {
alert('The File APIs are not fully supported in this browser.');
}
};
HTML:
<div>
<div>
<label for="filePicker">Choose or drag a file:</label><br/>
<input type="file" id="filePicker">
</div>
</br>
<div>
<h1>Base64 encoded version</h1>
<textarea id="base64textarea"
placeholder="Base64 will appear here"
cols="50" rows="15">
</textarea>
</div>
</div>
EDIT: Thank you for your answers, they were really helpful.
You simply can't do what you are trying to do. Setting the path for an input element through Javascript is not possible, as a security measure. Please check here: How to resolve the C:\fakepath?
You can launch chromium, chrome browser with --allow-file-access-from-files flag set, use fetch() of XMLHttpRequest() to request file from local filesystem.
fetch("file:///path/to/file")
.then(response => response.arrayBuffer())
.then(ab => {
// do stuff with `ArrayBuffer` representation of file
})
.catch(err => console.log(err));
See also Read local XML with JS
The File API is not good to read local files without user intervention, but the Web API is (of course, within its limitations, like not working in Chromium without explicitly enabling access to local files and whatnot).
So, here it is, in case someone else needs a working example of how to load a local file without user intervention, i.e., without requiring user to push any INPUT button (but still giving the user a means to abort the loading).
Parameters: file name, request type (text, blob etc.), MIME type and a function to be executed after the file is completely loaded. File is loaded in variable X, which is then used to populated an object.
To abort the file reading, just click on the progress bar (also, just an example, not essential for the program to work). Because it is asynchronous, as many files as wanted may be read at the same time (one progress bar is created for each file).
I only created examples for a text file and a video, but it should work with any kind of files.
<html>
<head>
<meta charset="utf-8"/>
<script type="text/javascript">
function LoadFile(FileName,RespType,FileType,RunMe)
{ var AJAXFileReader=new XMLHttpRequest();
// Creates new progress bar.
var ProgressBar=CreateSVGProgBar("ProgressBars");
AJAXFileReader.addEventListener("progress",
function FRProgress(AJAXFREvt)
{ // Calculate progress.
var X=-1;
if (AJAXFREvt.lengthComputable)
X=Math.trunc(AJAXFREvt.loaded/AJAXFREvt.total*100);
ShowProgressBar(ProgressBar,FileName,X);
});
AJAXFileReader.addEventListener("error",function FRFailed()
{ // This will be executed if an error occurs.
console.log("Error:",this.status);
});
AJAXFileReader.addEventListener("timeout",function FRTimeOut()
{ // This will be executed if the reading times out.
console.log("File reading timed out!");
});
AJAXFileReader.addEventListener("abort",
function FRCancel()
{ // This will confirm reading was aborted.
console.log("File reading cancelled by user!");
});
ProgressBar.addEventListener("click",
function KillMe()
{ // Adds an abort command to the object.
console.log(AJAXFileReader.readyState);
if (AJAXFileReader.readyState!=4)
{ console.log("Aborting file reading...");
AJAXFileReader.abort();
}
ProgressBar.removeEventListener("click",KillMe);
},
false);
AJAXFileReader.addEventListener("load",
function Finished()
{ // When reading is finished, send data to external function.
if ((this.readyState==4)&&(this.status==200))
{ ShowProgressBar(ProgressBar,FileName,100);
RunMe(this.response);
//ProgressBar.click();
}
},
false);
AJAXFileReader.open("GET",FileName,true);
AJAXFileReader.overrideMimeType(FileType);
AJAXFileReader.responseType=RespType;
AJAXFileReader.timeout=10000; // Setting time-out to 10 s.
AJAXFileReader.send();
}
function CreateSVGProgBar(AnchorId)
{ // Creates new SVG progress bar.
var Parent=document.getElementById(AnchorId);
var NewSVG=document.createElementNS("http://www.w3.org/2000/svg","svg");
NewSVG.setAttribute("viewBox","0 0 102 22");
NewSVG.setAttribute("width","102");
NewSVG.setAttribute("height","22");
Parent.appendChild(NewSVG);
return NewSVG;
}
function ShowProgressBar(E,N,X)
{ // Show progress bar.
var P=X<0?"???":X+"%";
E.innerHTML="<text x=\"50\" y=\"16\" font-size=\"12\" fill=\"black\" stroke=\"black\" text-anchor=\"middle\">"+N+"</text><rect x=\"1\" y=\"1\" width=\""+X+"\" height=\"20\" fill=\""+(X<100?"#FF0000":"#0000FF")+"\" stroke=\"none\"/><rect x=\"1\" y=\"1\" width=\"100\" height=\"20\" fill=\"none\" stroke=\"black\" stroke-width=\"1\"/><text x=\""+X/2+"\" y=\"16\" font-size=\"12\" fill=\"black\" stroke=\"black\" text-anchor=\"middle\">"+P+"</text>";
}
function TracerOn(X)
{ // This will be executed after the file is completely loaded.
document.getElementById("Tron").innerHTML=X;
}
function PlayIt(X)
{ // This will be executed after the file is completely loaded.
var blob_uri=URL.createObjectURL(X);
document.getElementById("MagicalBox").appendChild(document.createElement("source")).src=blob_uri;
}
function Startup()
{ // Run after the Page is loaded.
LoadFile("example.txt","text","text/plain;charset=utf-8",TracerOn);
LoadFile("video.mp4","blob","video/mp4",PlayIt);
}
</script>
</head>
<body onload="Startup()">
<div id="ProgressBars"></div>
<div id="Tron">Text...</div>
<video id="MagicalBox" width="400" controls>Video...</video>
</body>
</html>

How to Change Background Image Based on User Input | HTML, CSS, JS

I have done a lot of research on how to do this, yet I can't seem to find a specific answer. I am trying to allow the user to input a file from their computer, and turn that file into the background of the webpage. My following code is shown below:
<head>
<script>
function changeBackground() {
var input = document.getElementById("background").value;
localStorage.setItem("Background", input);
var result = localStorage.getItem("Background");
$('body').css({ 'background-image': "url(" + result + ")" });
}
</script>
</head>
<body>
<input id="background" type="file" onchange="changeBackground()">
</body>
If someone could please explain to me what I need to do to get this to work, I would very much appreciate it. I already understand I need to use localStorage to make sure that the selected background is remembered, I am just having trouble getting the background to change. If there is already an article on how to do this, I would appreciate a link to it. Thanks!
EDIT
Nikhil and user6003859 explained to me why it isn't working. I guess I just need to figure out how to use Ajax and PHP to change it. If anyone has more advice on this, I would love to hear it. Thanks everyone for helping me solve this problem.
Modern browsers normally restrict access to the user's local files (in this case an image). What you're trying to do is display an image from the user's local filestorage, via the path you get from the <input type='file' /> value.
What you should instead be doing, is uploading the image to your server (probably with ajax, so it feels seamless), and then displaying the file from your server on to your page.
EDIT: Even though this is kind of a new question, I'll give you an example on how to change an element's background based on a URL provided by the user:
var inp = document.getElementById('inp');
var res = document.getElementById('res');
inp.oninput = function()
{
res.style.backgroundImage = 'url(' + inp.value + ')';
};
div
{
width: 5em;
height: 5em;
}
<input type='text' id='inp' />
<div id='res'>
</div>
It's better practice to use file reader.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#file").change(function(){
var length=this.files.length;
if(!length){
return false;
}
changeBackground(this);
});
});
// Creating the function
function changeBackground(img){
var file = img.files[0];
var imagefile = file.type;
var match= ["image/jpeg","image/png","image/jpg"];
if(!((imagefile==match[0]) || (imagefile==match[1]) || (imagefile==match[2]))){
alert("Invalid File Extension");
}else{
var reader = new FileReader();
reader.onload = imageIsLoaded;
reader.readAsDataURL(img.files[0]);
}
function imageIsLoaded(e) {
$('body').css({ 'background-image': "url(" + e.target.result + ")" });
}
}
</script>
</head>
<body>
<input type="file" name="" id="file" value="Click">
</body>
</html>
You cannot do that purely with client-side because of security reasons.
The moment you upload say an image, the browser gives it a "fakepath" like so:
C:\fakepath\<filename>.png
This is a security implementation of the browser - the browser is protecting you from accessing your disk structure.
Hence when you check the value of your input after uploading, you would get the above fakepath ie. C:\fakepath\<filename>.png. Using this as the background obviously would not work.
Usually to achieve this you need to first store it in a server, then fetch the value from the server and apply the background.
To use a local file, store it in a blob
<head>
<script>
function changeBackground() {
var backgroundFile = document.getElementById("background").files[0];
$('body').css({ 'background-image': "url(" + URL.createObjectURL(backgroundFile) + ")" });
}
</script>
</head>
<body>
<input id="background" type="file" onchange="changeBackground()">
</body>

Categories

Resources