I have html page, on that page I have input and button
I want to save the string in input into existing file like 'text.txt`
this is my html code
<input id="sub" dir="ltr" type="text" placeholder="type something">
<button id="myBtn" onclick="myFunction()" class="main-btn">Subscribe</button>
and this is my javascript function
<script>
function myFunction() {
const fs = require('fs')
let data = document.getElementById("sub").value + "\r\n";
fs.writeFile('Output.txt', data, (err) => {
if (err) throw err;
})
}
</script>
but it's not working
You can't just access the Filesystem from your browser.
Your options depend on what you are trying to achieve.
1. Save a txt file on the users local filesystem
You can create a "downloadable" element directly from JS. Depending on the browser the user will be prompted to allow downloads and/or where to store the file. You cannot access the file afterwards.
function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
// Start file download.
download("hello.txt","This is the content of my file :)");
Source: https://www.codegrepper.com/code-examples/javascript/javascript+download+text+as+txt+file
2. Save data inside the browser so you can read/write whenever the users visits your website
The localstorage API can create small keyed objects (like 5-10 mb) on the user system. You can read/write anything to or from it that is serializable.
localStorage.setItem('myCat', 'Tom');
const cat = localStorage.getItem('myCat');
localStorage.removeItem('myCat');
Here: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
3. Save a file/data on your server
If you need the file on the server itself, you must create a backend with php, nodejs etc. Then you must implement an endpoint that accepts the data you want to save and inside nodejs you can import the "fs" and directly write files to it.
const fs = require('fs')
const content = 'Some content!'
fs.writeFile('/Users/joe/test.txt', content, err => {
if (err) {
console.error(err)
return
}
//file written successfully
})
Source: https://nodejs.dev/learn/writing-files-with-nodejs
Related
I am working on my own project where I want to create an application, which runs on android and iOS. I decide using HTML, CSS and JavaScript for creating a PWA. The app should enable the user to manage recips for tart incl. Cost calculation. My problem is, that I want to save the recips/ingredients in form of a table. The data should be stored permanently locally on the device. With the method "localstorage" the data are only saved temporarily. I don't want to host a webserver/database. The data should not be lost when the user delete the local cache of the browser.
Is it possible to store general data with java script, for example in a text file, outside of the browser's cache?
In your case indexedDB would be my go to solution. It can be deleted by a user as all data stored in the browser. Browser can't store data in text files (at least as per October 2021)
It is possible. but it's not straightforward it must be done manually by the user.
You can generate your DB as a downloadable file -eg. .txt or .csv- and provide the download link for the user or just auto-download it.
here's an example.
function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
// Start file download.
document.getElementById("dwn-btn").addEventListener("click", function(){
// Start the download of yournewfile.txt file with the content from the text area
var text = document.getElementById("text-val").value;
var filename = "yournewfile.txt";
download(filename, text);
}, false);
to load the data you can create an import button that receives the data and populates the table.
here's how you can read file data
function readImage(file) {
// Check if the file is text.
if (file.type && !file.type.startsWith('text/')) {
console.log('File is not an textfile.', file.type, file);
return;
}
const reader = new FileReader();
reader.addEventListener('load', (event) => {
img.src = event.target.result;
});
reader.readAsDataURL(file);
}
I recommend using this approach with indexedDb or local storage.
I'm trying to find a way to write to a text file using node.js but I was trying to get the input from the HTML DOM. How do you write the output from the DOM to a text file using fs.writeFile?
Here's some code that doesn't work but thought it might be relevant. Thanks
<h3>A demonstration of how to access a Text Field</h3>
<input id="myText">
<button onclick="myFunction()">Try it</button>
<script>
const fs = require('fs')
function myFunction() {
var content = document.getElementById("myText").value;
}
fs.writeFile('./test.txt', content, err => {
if(err){
console.log(err);
return
}
})
</script>
You cannot write file directly from a browser to local computers.
That would be a massive security concern.
*You also cannot use fs on client-side browser
Instead you get inputs from a browser, and send it to your server (NodeJs), and use fs.writeFile() on server-side, which is allowed.
What you could do is:
Create a link and prompt to download.
Send to server and response with a download.
Use native environment like Electron to able NodeJs locally to write into local computer.
What I assume you want to do is 1
Is that case you could simply do:
function writeAndDownload(str, filename){
let yourContent = str
//Convert your string into ObjectURL
let bom = new Uint8Array([0xef, 0xbb, 0xbf]);
let blob = new Blob([bom, yourContent], { type: "text/plain" });
let url = (window.URL || window.webkitURL).createObjectURL(blob);
//Create a link and assign the ObjectURL
let link = document.createElement("a");
link.style.display = "none";
link.setAttribute("href", url);
link.setAttribute("download", filename);
//Automatically prompt to download
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
writeAndDownload("Text you want to save", "savedData")
I'm making a web service that will return some generated zip files to a client.
Currently I did a really simple code for my test and when I query directly this service the ZIP file is well returned. In a near future, I'll need to pass some parameters through the header and so a simple link on the client side will not do the job.
So I decided to use XmlHttpRequest on my client to query the resource and download it as a simple file. The problem comes here, when I generate the download with the server response, the zip file doesn't work.
Here is the NodeJS code (with express) :
.get('/myservice', function(req, res)
{
res.setHeader('Content-Type', 'application/zip');
const JSZip = require('jszip');
const zip = new JSZip();
zip.file('hello.txt', 'Hello world\n');
zip
.generateAsync({type: 'nodebuffer'})
.then(function(content)
{
res.send(content)
}.bind(res));
}
Here is the client side Javascript that call the service and then make a file from the answer :
var req = new XMLHttpRequest();
req.open("GET", "https://mydomain/myservice", false);
req.send(null);
function download(filename, text)
{
var element = document.createElement('a');
element.setAttribute('href', 'data:application/zip;charset=base64,' + text);
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
console.log(req.responseText)
download('test.zip', req.responseText);
I think that I completely miss understand the encoding on the client, but I didn't find the solution.
The downloaded file, when unzip, give me a file that contain the same zip that also do the same thing.
When I call the service with XmlHttpRequest, it is well called and does not throw any error.
I'm using JSZip to generate the zip.
I precise that I can't use blob on generateAsync from JSZip because that throw me an error.
Any solution ?
You dont need to make it so complicated. As you are piping a file already. Just use window.open('/myservice'); as the browser will handle the fact its a file and keep the current page open and download the file.
https://codesandbox.io/s/hardcore-euclid-9nkft
I'm building a page for my angular2 web application where a user can select customers from a list and print off letters to mail them. These letters were uploaded as PDFs and are stored as varbinary in the database.
In the case of multiple selections, I'm simply appending byte[]'s so the user will print one document containing all of the letters to send to customers.
I'm able to pull the blob successfully from the API and return it with the content type application-pdf but then I don't know what to do with it from there.
Here's my Angular2 Component API Call:
this.printQueueService.getPrintContent(printRequests) //customers to receive letters
.subscribe((data: Blob) => {
var element: HTMLIFrameElement = <HTMLIFrameElement>document.getElementById('printFile');
element.innerText = data + ""; //what do I do with the blob?
element.contentWindow.print();
});
HTML Element:
<iframe id="printFile" style="display:none"></iframe>
I know I can just download the PDF and prompt the user to print using a PDF Viewer, but I'd rather not force users to go through extra steps.
I'd also rather not try to render the PDF in the browser and print because it assumes users have the proper plugins and browsers support it.
What options do I have for printing a blob in the browser?
As per suggestions from Daniel A. White, I solved this issue. I decided not to use an IFrame because these print files could be massive and the print() function includes the page name as footnotes.
Instead, I chose to open the generated PDF in a new tab as follows:
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(data, "PrintedLetters.pdf"); //IE is the worst!!!
}
else {
var fileURL = URL.createObjectURL(data);
var a: HTMLAnchorElement = document.createElement('a');
a.href = fileURL;
a.target = '_blank';
document.body.appendChild(a);
a.click();
}
I am downloading files using HTML5 from below codes that you can see live in action at JSBIN HTML5 Download File DEMO and its working perfectly file and downloading my files at my browser default Download Folder.
<!DOCTYPE html>
<html>
</head>
</head>
<body>
<table>
<tr><td>Text To Save:</td></tr>
<tr>
<td colspan="3">
<textarea id="inputTextToSave" style="width:512px;height:256px"></textarea>
</td>
</tr>
<tr>
<td>Filename To Save As:</td>
<td><input id="inputFileNameToSaveAs"></td>
<td><button onclick="saveTextAsFile()"> Save Text To File </button></td>
</tr>
<tr>
<td>Select A File To Load:</td>
<td><input type="file" id="fileToLoad"></td>
<td><button onclick="loadFileAsText()">Load Selected File</button><td>
</tr>
</table>
<script type='text/javascript'>
function saveTextAsFile()
{
var textToWrite = document.getElementById("inputTextToSave").value;
var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs").value;
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
if (window.webkitURL != null)
{
// Chrome allows the link to be clicked
// without actually adding it to the DOM.
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
}
else
{
// Firefox requires the link to be added to the DOM
// before it can be clicked.
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
}
downloadLink.click();
}
function destroyClickedElement(event)
{
document.body.removeChild(event.target);
}
function loadFileAsText()
{
var fileToLoad = document.getElementById("fileToLoad").files[0];
var fileReader = new FileReader();
fileReader.onload = function(fileLoadedEvent)
{
var textFromFileLoaded = fileLoadedEvent.target.result;
document.getElementById("inputTextToSave").value = textFromFileLoaded;
};
fileReader.readAsText(fileToLoad, "UTF-8");
}
</script>
</body>
</html>
But I want to download it on different location. Like I am using this code offline and just have the upper code in my index.html file. When I run this file in my browser from file:///C:/Users/Public/Desktop/ then it download the file and save it at file:///C:/Users/Public/Downloads/. So I want to download this file from where its called. For this I am picking the path from the following code. and its giving me the path as /C:/Users/Public/Desktop/ so I want to save file here. Whereever my this index.html file will go, it will download the file and save it along index.html file. How is this possible?
var url = window.location.pathname;
var folderpath = url.substring(0,url.lastIndexOf('/')+1);
alert(folderpath);
It's not possible because this poses a security risk. People use fairly real information for their folder structure and accessing the folder names in itself poses an immediate risk. As described here:
Get browser download path with javascript
Most OSs tend to just default to a Download location and this is something the user decides through the Browser they use. Not the website.
In Chrome, Download location setting can be found at chrome://settings/downloads
This is now possible in most Chromium based desktop browsers (and safari soon), using the File System Access API. https://caniuse.com/native-filesystem-api
An example on how to do this can be found here: https://web.dev/file-system-access/#create-a-new-file
Something along the lines of:
async function getHandle() {
// set some options, like the suggested file name and the file type.
const options = {
suggestedName: 'HelloWorld.txt',
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
// prompt the user for the location to save the file.
const handle = await window.showSaveFilePicker(options);
return handle
}
async function save(handle, text) {
// creates a writable, used to write data to the file.
const writable = await handle.createWritable();
// write a string to the writable.
await writable.write(text);
// close the writable and save all changes to disk. this will prompt the user for write permission to the file, if it's the first time.
await writable.close();
}
// calls the function to let the user pick a location.
const handle = getHandle();
// save data to this location as many times as you want. first time will ask the user for permission
save(handle, "hello");
save(handle, "Lorem ipsum...");
This will prompt the user with a save file picker where he can choose a location to save the file to. In the options, you can specify a suggested name and the file type of the file to be saved.
This will return a file handle, which can be used to write data to the file. Once you do this, the user is asked for write permission to the created file. If granted, your app can save data to the file as many times as you like, without re-prompting the user, until all tabs of your app are closed.
The next time your app is opened, the user is prompted for permission again, if you use the same file handle again (the handles can be saved in IndexedDB to persist them across page loads).
The File System Access API also allows you to let the user pick an existing file, for your app to save later. https://web.dev/file-system-access/#ask-the-user-to-pick-a-file-to-read