Write to a local JSON file from the browser [duplicate] - javascript

This question already has answers here:
Download JSON object as a file from browser
(14 answers)
Closed 7 months ago.
I'm trying to write to my local JSON file with javascript, I'm getting it from my HTML, changing it and want to write it back. I found how to read it from here but didn't find how to write to it back to the json file.
Note: I want to this without Node.js , 'fs' won't help..
My code to get the JSON file:
<script type="text/javascript" src="data.json></script>
<script type="text/javascript" src="javascrip.js"></script>
var mydata = JSON.parse(data);
Then I changed the value of the 'name', for example.
mydata["name"] = "NewName";
And then I want to send it back to the json file, update it.
I didn't really find any code to do so.

While you can't directly write to the file system due because of security constraints, you can trigger a save dialog to request the user to save the file. I use this function which works on all recent releases of the major browsers.
function download(data, filename) {
// data is the string type, that contains the contents of the file.
// filename is the default file name, some browsers allow the user to change this during the save dialog.
// Note that we use octet/stream as the mimetype
// this is to prevent some browsers from displaying the
// contents in another browser tab instead of downloading the file
var blob = new Blob([data], {type:'octet/stream'});
//IE 10+
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(blob, filename);
}
else {
//Everything else
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
document.body.appendChild(a);
a.href = url;
a.download = filename;
setTimeout(() => {
//setTimeout hack is required for older versions of Safari
a.click();
//Cleanup
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}, 1);
}
}
It is also worth mentioning that HTML5 spec has a download attribute, but it isn't currently supported on IE.

As ArtemSky said, You can't write to the local file system. The way to accomplish what you want to do would be to use a server that can write to it's local file system or a database or whatever.
So you would want to have the data stored somewhere, either a local file on the server, in the cloud, etc. or a database of some sort. Then you would set up an API on the server that you could call remotely to get the data via an XMLHttpRequest(XHR)
Then you would create another API method you can use to send the data back and then call that with the updated/new data.
Writing to the local file system is a security concern because if anyone who can write code could overwrite your system files otherwise. Preventing the ability to write to the local file system is the only way to make the web safe.

You can't write to file system due to security constraints of the browser.
You can do that only this way - https://stackoverflow.com/a/30800715/6149665

Related

Can JavaScript save values without PHP?

I am begginer in programming. I have made these stopwatch for speedsolves using HTML and JavaScript.
Is there any way of saving my average solve time using Javascript only?
For instance i have some variable with loop:
var time=0;
if (true){
time++;
}
and after I close the HTML site, close the browser and turn off the computer, after opening the site again I want to get var time=value before closing the site
I'm familiar with PHP and databases, but I dont really want to use it, since I have to start a server.
If you just want to save data for your program to read later, you can use localStorage or sessionStorage. That is, localStorage.setItem('name', 'value') and localStorage.getItem('name') to read it. (They're the same, except sessionStorage gets cleared once the browser is closed, while localStorage doesn't.)
To actually save a file, you can do that only by triggering it to be downloaded. First you create a Blob with the content you want for the file, then you get an object URL for that Blob. Assign the URL to the href of a link with a "download" attribute and click it.
function saveFile(contents, name) {
const blob = new Blob([contents], {type: 'text/plain'});
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.download = name;
link.href = url;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
Little more information will help, but, as you are talking of storage, you can use localstorage or sessionstorage within javascript to store the values.
For saving files on the local device, you can use FileSaver. But in your situation, an easier solution would be to take advantage of localstorage.
Note: From what I've found, LocalStorage won't work without a server. So if you want to store data and aren't using a server, FileSaver may work better. Then again, I don't know if it's possible to load the data in a file saved in FileSaver into javascript in a browser, especially if you don't have a server

Is it possible to stream an octet stream being generated in javascript?

Lets suppose a case where a huge string is generated from a small string using some javascript logic, and then the text file is forced to be downloaded on the browser.
This is possible using an octet-stream download by putting it as an href , as mentioned in this answer :
Create a file in memory for user to download, not through server.
function download(filename, text) {
var pom = document.createElement('a');
pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
pom.setAttribute('download', filename);
pom.click();
}
But this solution requires 'text' to be fully generated before being pushed for the download,
hence it will have to be held in browser memory fully .
Is it possible to stream the text as it gets generated using CLIENT SIDE LOGIC ONLY ?
For example :
var inputString = "A";
var outStr = "";
for(var i = 0; i < 10000000 ; i++)
{
/* concatenate inputString to output on the go */
}
Yes & no. No because there's not a way to write to files with just client-side javascript. Kinda. You can prompt a user to download & save a file, but as you mentioned, the code must generate the whole file before that download happens. Note: By "stream" I assume you mean stream to file (constantly write to a file) & by "CLIENT SIDE LOGIC ONLY" I assume you mean in the browser.
Looks like Mozilla has been working on a way to let client-side code interact with files. Here comes the yes. Kind of. They have their own file system api that lets you interact with (write to) the local machines file system. Specifically, there's a function that lets you write an input stream to a file. However, there's a few asterisks:
1) looks like that whole system is being deprecated; they encourage developers to use OS.file over File I/O
2) You have to use XPConnect, a system that lets you access Mozilla's XPCOM (component library) in javascript. If you want to do this in the browser, it looks like only firefox extensions have the proper permissions to interact with those components (). If you didn't want to do this in the browser, you obviously could just use node.
Assuredly, more complications are bound to show up during implementation. But this looks like the most sure path forward, seeing as how OS.File gives you access to functions like OS.File.writeAtomic() & basic write to file
That being said, it's not that great of a path, but hopefully this gives you a solid starting point. As #dandavis mentioned, browsers (i.e. "client side logic") are designed to not allow this sort of thing. It would be an incredibly huge oversight / security flaw if a website could interact with any user's local file system.
Additional resources:
Wikipedia on XPConnect
Guide on working with XPCOM in javascript - may not be that useful
There is a way to do this, but it relies on a Chrome only Filesystem API. We will create and write to a temporary file in a sandboxed file system and the copy it to the regular file system once we are done. This way you do not have to store the entire file in memory. The asynchronous version of the Chrome API is not currently being considered for standardization by W3C, but the synchronous verison (which uses web workers) is. If browser support is a concern, then this answer is not for you.
The API works like this:
First, we get the requestFileSystem() function from the browser. Currently it is prefixed by "webkit":
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
Next, we request a temporary file system (this way we do not need to ask for user permission):
var fileSystem; //This will store the fileSystem for later access
var fileSize = 1024*1024 //Our maximum file system size.
function errorHandler(e) {
console.log('Error: ' + e.name);
}
window.requestFileSystem(window.TEMPORARY, fileSize, function (fs) { fileSystem = fs; }, errorHandler);
Now that we have access to the file system it is time to create a file:
var fileOptions = {
create: true, //If the file is not found, create it
exclusive: false //Don't throw an error if the file doesn't exist
};
Here we call the getFile() function, which can create a file if it doesn't exist. Inside of the callback, we can create a new fileWriter for writing to the file. The fileWriter is then moved to the end of the file, and we create a new text blob to append to it.
fileSystem.root.getFile(fileName, fileOptions, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.seek(fileWriter.length);
var blob = new Blob([STRING_TO_WRITE], {type: 'text/plain'});
fileWriter.write(blob);
}, errorHandler);
});
Note that this API does not save to the normal, user filesystem. Instead, it saves to a special sandboxed folder. If you want to save it to the user's file system, you can create a filesystem: link. When the user clicks on it, it will prompt them to save it. After they save it, you can then remove the temporary file.
This function generates the filesystem link using the fileEntry's toURL() function:
var save = function () {
var download = document.querySelector("a[download]");
if (!fileSystem) { return; }
fileSystem.root.getFile(fileName, {create: false, exclusive: true}, function(fileEntry) {
download.href = fileEntry.toURL();
}, errorHandler);
}
Using a link with the download attribute will force the download of the file.
<a download></a>
Here is a plunker that demonstrates this: http://plnkr.co/edit/q6ihXWEXSOtutbEy1b5G?p=preview
Hopefully this accomplishes what you want. You can continuously append to the file, it won't be kept in memory, but it will be in the sandboxed filesystem until the user saves it to the regular filesystem.
For more information take a look at this HTML5rocks article or this one if you want to use the newer, synchronous Web Worker API.
I would have suggest it the way #quantumwannabe describes it, using temporary sandbox file to append chunks.
But there is a new way that can be used today (behind a flag) but will be enabled in the next version of chrome (52)
And here is where i will make #KeenanLidral-Porter answer incorrect. And #quantumwannabe answer a unnecessary step
Because there is now a way to write a stream to the filesystem directly: StreamSaver.js
It acts as if there was a server sending octet-stream header and tells the browser to download chunks of data with help of a service worker
const writeStream = streamSaver.createWriteStream('filename.txt')
const encoder = new TextEncoder
let data = 'a'.repeat(1024) // Writing some stuff triggers the save dialog to show
let uint8array = encoder.encode(data + "\n\n")
writeStream.write(uint8array) // Write some data when you got some
writeStream.close() // End the saving

How to store file in a browser using JavaScript

I am working for a prototype of website(Only Browser based). There is a part where I need to upload some files.Here I am using JavaScript and HTML.
Whenever user wants to upload(Like Browse button in applications) some files then it will available for next time.I am unable to do this.
Question Can we save/store/upload a file using JavaScript/HTML in browser only(Not server )??
Thanks
Downloading file directly to user's file-system
If you by save/store mean directly to user's computer/file system then no, this is not possible due to security reasons.
However, you can initiate a download which will pop up a "save as" type of requester and allow user to accept or deny to download the file.
There are more than one way to initiate a download. An interesting one is the new download attribute for the anchor tag where you can specify a file name as well as automatically initiate the download setting its href to a data-uri or something else you want to reference for download:
Click to download
Local storage mechanisms
If you simply want to save the file locally you can use one of the many local storage mechanisms such as:
File system API (only supported in Chrome currently and the new Opera. In draft status)
Indexed DB (allows Blob objects. Good support)
Web SQL (deprecated but widely in use)
Web Storage (very good support but only stores strings and has limited space, objects can be saved as JSON strings)
Note that all of these as sand-boxed and only available in the browser using the same origin as they was written from. The data may or may not be discarded at any point as well (by user or by browser) so they are not a "safe" storage (always keep a server copy or a way to regenerate the data).
Yes, it's possible via FileSystem API (currently only Chrome and Opera).
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
document.querySelector('input[type="file"]').onchange = function(e) {
var files = this.files;
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
// Duplicate each file the user selected to the app's fs.
for (var i = 0, file; file = files[i]; ++i) {
// Capture current iteration's file in local scope for the getFile() callback.
(function(f) {
fs.root.getFile(f.name, {create: true, exclusive: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.write(f); // Note: write() can take a File or Blob object.
}, errorHandler);
}, errorHandler);
})(file);
}
}, errorHandler);
};
"Can we save/store/upload a file using JavaScript/HTML in browser only(Not server )??"
Ans. is No. If you want to retain the uploaded file then you need to store it on server.
The moment the browser tab is closed the file will get lost.
Alternative: What you can do is store the name of the file on server and whenever user request the file then ask him to upload it.
For uploading the file into memory you can refer to this link .
Live Demo

How to generate and prompt to save a file from content in the client browser? [duplicate]

This question already has answers here:
Create and save a file with JavaScript [duplicate]
(11 answers)
Closed 7 years ago.
I have a situation where I need to give my users the option to save some data stored locally in their client memory to disk. The current workaround I have is having a handler like this
(define-handler (download-deck) ((deck :json))
(setf (header-out :content-type) "application/json"
(header-out :content-disposition) "attachment")
deck)
which does exactly what it looks like. The client sends their data up, and saves the returned file locally.
This seems stupid.
Please, please tell me there's a better, simpler, cross-browser way to let a client save some local data to their disk with a file-save dialog box.
Every answer I read on the subject either says "no, you can't save files with javascript" or "yes, there's this one semi-documented piece of the Chrome API that might let you do it in three pages".
This "FileSaver" library may help. If you want it to be reasonably cross-browser, you'll also need this to implement the W3C Blob API in places it's not already implemented. Both respect namespaces, and are completely framework agnostic, so don't worry about naming issues.
Once you've got those included, and as long as you're only saving text files, you should be able to
var blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
saveAs(blob, "hello world.txt");
Note that the first argument to new Blob has to be a list of strings, and that you're expected to specify the filename. As in, the user will see this file being downloaded locally, but won't be able to name it themselves. Hopefully they're using a browser that handles local filename collisions...
This is my code:
<a id='tfa_src_data'>Export</a>
document.getElementById('tfa_src_data').onclick = function() {
var csv = JSON.stringify(localStorage['savedCoords']);
var csvData = 'data:application/csv;charset=utf-8,'
+ encodeURIComponent(csv);
this.href = csvData;
this.target = '_blank';
this.download = 'filename.txt';
};
You can use various data types.
Depending on what you are trying to do exactly, the HTML5 local storage concept might help you.
So what is HTML5 Storage? Simply put, it’s a way for web pages to store named key/value pairs locally, within the client web browser. Like cookies, this data persists even after you navigate away from the web site, close your browser tab, exit your browser, or what have you. Unlike cookies, this data is never transmitted to the remote web server (unless you go out of your way to send it manually). http://diveintohtml5.info/storage.html
There's also the Filesystem API (so far only implemented in Chrome AFAIK)
http://www.html5rocks.com/en/tutorials/file/filesystem/

Use javascript to get the directory of a file

I am using an input of type=file and I am trying to figure out how to extract the file location from it. I am using this code:
file = $("#uploadFiles").attr("files")[0];
var fileName = file.fileName;
var formData = 'uploadFile=' + fileName;
and when i alert formData, it says "uploadFile=temp.jpg"
What I want is the alerted message to be something like:
"uploadFile=C:\user\doug\documents\pictures\temp.jpg"
But I don't know the attribute of the file object to put in for file.fileName
Generally, you can only rely on the filename being accessible - used mainly as a preliminary extension checking (e.g. (jpe?g|png|gif)$) on the client side (which only serves to benefit the user, to stop them from uploading a 5mb file that will be not validate on the server anyway).
You can access whatever the browser will give you with...
jQuery
$('file[type=input]').val();
JavaScript
document.getElementById('file-input').value;
For security reasons, this is completely impossible in modern browsers.

Categories