Keeping information about js file in localStorage - javascript

I want to create plugin mechanizm. It is, you can load js file on my website and run your js "plugin" (function) when this plugin is set to run (toggled as running).
All this I want to do without any server.
I mean, I want to keep in localstorage js files or path to this files.
It looks to be hard to do because js can't easy access files path.
I handle file by <input type="file"/>
And I react on onchange event. I get event where I can find selected file by event.srcElement.files[0]
With that I can create URL of that object by : URL.createObjectURL(event.srcElement.files[0])
And I tried to store that URL in localstorage but this URL is temporary.
Also I tried to store whole event or just file (event.srcElement.files[0]).
But I need to create string from that if I want to put it to the function .setItem :
localStorage.setItem("functionURL", JSON.stringify(this.functionURL));
.toString() creates [Object Event/File]
JSON.stringify() creates {} from [Object Event/File]
So, maybe is there a way to somehow remember file which we can use as a function without any server ?

So, maybe is there a way to somehow remember file which we can use as a function without any server ?
Basically, no. :-) Web storage only stores strings. You can't use a string to access a file on the user's local filesystem from your web page, for obvious security reasons.
You could, instead:
Make it possible for them to "upload" the file into your page (without a server) by having them identify the file in an input[type=file], reading its text (via the File API), and then storing that text in local storage
On page load, if local storage has code to run, run it
Offer the user a way to delete or update the code they've uploaded to the page
Since all of that happens in the browser, you don't need a server.
Web storage does have size limits, though they're pretty generous, (around 2.5-5MB) and per-origin, so you have that largely to yourself. But if you run into those limits, you could take it further by caching those files via a service worker, but the complexity goes up markedly. I'd start with web storage and only move on if you really need to support massive files.
#1 (reading the script file the user identifies via an input[type=file]) is really simple on modern browsers:
var file = input.files[0];
var fr = new FileReader();
fr.onload = function() {
// Use `fr.result` here, it's a string containing the text
};
fr.readAsText(file);

Related

Ionic - File upload without reading into memory

I'm trying to find a way to upload large files without having to read them all into memory. I need to be able to post multiple files along with a data payload in a single request. I'm able to accomplish it with standard HTML inputs, something like this:
<input id="myFile1" type="file" />
<input id="myFile2" type="file" />
<input id="myData" type="text" />
And javascript code like this:
var file1 = document.getElementById('myFile1').files[0];
var file2 = document.getElementById('myFile2').files[0];
var data = document.getElementById('myData').value;
var formData = new FormData();
formData.append('myFile1', file1, file1.name);
formData.append('myFile2', file2, file2.name);
formData.append('myData', data);
Even when selecting a large file this is very fast. Keep in mind I'm only referring to the client side performance, as the actual upload portion is going to be bottlenecked by the users network speed.
So now comes my problem: I need to use the Ionic camera plugin to allow a user to either record video or select video files on their phone. But when a user picks a file, you aren't immediately given a File object to work with; a user picks a file, then you are given a file URL and have to convert that into a Blob in order to post it to a server. However, as you can see from this stackoverflow answer, you have to read the entire file contents into memory to create the Blob object. This is slow (and very inefficient) when selecting a large file.
Does anyone know of a way to get a Blob or File object without reading everything into memory? I looked at the File and Blob API documentation but from what I see there isn't a way, unless I'm missing something. I'm wondering how the File API works behind the scenes when using a standard HTML input and choosing a file, because as shown by the example above, you're immediately given access to a File object (which is also a Blob) and it's very fast even for large files.

How can I get information from a local text file without browsing?

So what I'm trying to do is get text from a file in the same directory as my html file using JavaScript. I want to store an array inside a text file and change it whenever i want instead of constantly having to go into the code, save it, check if it works etc.
I've tried looking around but couldn't find any clear information, most of what I found is using .readAsBinaryString, etc..
I'm mostly seeing things like this but i can't seem find anything which is actually getting information from a textfile without making the person find the text file directory.
function storearray(newval){
var file = "file location;"
var txt = file.txt;
var array = txt.split("|");
txt = txt + newval + " | ";
return array;
}
To read a file from the user's disk you need to use FileReader and the user must explicitly select the file using a file input. (See JavaScript read file without using input).
To read a a file from the website you need to use Ajax (with fetch, XMLHttpRequest or a library that wraps around them like Axios). (See Using fetch from MDN).
If (as it seems here) you want to read data from the website but the website exists only on the user's disk then you still need to use Ajax but will usually run into security restrictions. Some browsers allow you to disable the security protection, but the general solution is to install a web server and load both HTML and the data file using HTTP.
Alternatively, you can store your data in JavaScript (you are generating an array from your text file, you can so that manually or have a build-time script do it) and just load it with a <script> element.

Again: how can I read a file using javascript

I could not find out why this part of my code doesn't work:
var loc = window.location.pathname;
var dir = loc.substring(0, loc.lastIndexOf('/'));
var FilePath = dir + "/" + FileName;
var file = new File("FilePath");
var reader = new FileReader();
reader.onload = function(e) {FileText = reader.result;}
reader.readAsText(file);
alert (FileText);
The intention is, I think, clear: FilePath contains the filename of a file (passed via parameter FileName) containing logging data (a plain ASCII text file, with one line per log entry), the file is located in the same directory as the web page is (loc), and I want to embed the text into my html document somewhere further down the code.
Since the logged lines are of different kinds (e.g. errors, warning, other blabla ...) each line needs to be parsed and processed.
I intended to split FileText into an array, and loop through it. I cannot, however, get readastext to work. Though, according to FireFox debugger, FilePath does contain the correct string, I get the NS_ERROR_FAILURE, which I, according to the sparse documentation I found about it, must consider to be the 'zillionst stupid way to say "File not found".
I found tons of other posts from people messing with the file API, and tons of snippets taken from the mozilla docs which don't help me out. I read that there are maybe other ways to read a file, e.g. through Ajax, JQuery ... but before I go that way ... is it really, really absolutely impossible to accomplish what I want using just plain JavaScript, and if it is possible, who can provide a code snippet?
Thanks very much,
Armin.
You have quotes around "FilePath":
var file = new File("FilePath");
This means it's going to try to load a file with the path "FilePath".
Pretty sure this is what you want:
var file = new File(FilePath);
On the other hand, Quentin is absolutely right. You're not going to be able to access local files if this code is running in a web page.
Since you are using window.location.pathname i assume that you are in a browser and want to use that code to "navigate" to files on the server based on the URL path.
I think your whole approach is wrong, and it would be a security issue to have something like that possible.
The File API can be used strictly on files selected by the user, and not on any file. The MDN description is self-explanatory:
Using the File API, which was added to the DOM in HTML5, it's now possible for web content to ask the user to select local files, then read the contents of those files. This selection can be done by either using an HTML element, or by drag and drop.
Yes, you can specify a path to any file in the File constructor method, but that doesn't mean you can access any file. Another excerpt from MDN:
This only works from privileged code, so web content can't do it. This protects users from the inherent security risks associated with allowing web content free access to the contents of their disks. If you pass a path to the File constructor from unprivileged code (such as web content), an exception will be thrown.
This code did the trick:
var objXMLhttp = new XMLHttpRequest()
objXMLhttp.open("GET",strFileName,true);
objXMLhttp.send();
and, in addition, an objXMLhttp.onreadystatechange=function() ... event handler must be implemented, which is the code acutally receiving the data, like so:
objXMLhttp.onreadystatechange=function()
{
if (objXMLhttp.readyState==4 && objXMLhttp.status==200)
{
var arrContents = objXMLhttp.responseText.split("\n"); // gotcha!
....
}
}
Easy win is to do an ajax request for the path...you should have your page that contains the js and files served by a web server. Any other way needs other priveleges and if you were to get files from a users computer without an uploader or anything like that would be a security breach

Pass File object to background.js from content script or pass createObjectURL (and keep alive after refresh)

My goal is to upload a file in the background task with a file coming from the content script.
I figured it's not possible to pass a File object directly from content script to the background because chrome.runtime.sendMessage JSON serialize the data.
It's possible to pass a string url to the file with URL.createObjectURL, which works. But the URL is tied to the document in the window on which it was created (current tab content script). If I refresh, navigates away, close the tab those urls are destroyed.
Read the entire file with FileReader and keep in memory is not an option because it'll crash the extension on large files.
Questions:
Keep the URL.createObjectURL alive?
Pass File object to background?
Upload a file in the background task with a file from the content script?
Pass file link to popup and submit form there, which then run in background?
You can use a SharedWorker to create a communication channel between your content script and background script that allows you to transfer DOM objects such as Files. For an example, see the code in Does chrome.runtime support posting messages with transferable objects?
A quick test shows that it is indeed possible to send a File to the background, but also shows that its internal state is corrupted: You can read the contents of the file using FileReader, but you cannot upload the file through XMLHttpRequest.
I've found a work-around though: Assuming that your File is stored in the file variable, you can use file.slice(0, file.size) instead of file to get a Blob that is still backed by the file and usable in XMLHttpRequest even after passing it to the background page.

maintaining reference to client files between sessions

I'm developing a web app that works with video files -- specifically, I have the user 'select' their video file through a form input, I then construct a URL reference to that file, and set the <video> source to that URL. This allows me to work with user supplied content, without having to upload the video -- something that seems unnecessary, and will lead to decreased performance.
Here's my very simple code for now:
// within a change event for a file input
var videoFile = e.currentTarget.files[0];
var fileURL = URL.createObjectURL(videoFile);
var videoNode.src = fileURL;
This works great. The problem: It doesn't allow me to store a reference to this video in between user sessions. I've tried to save the fileURL into a Mongo document, and then later reload that video file... and while this works sometimes, it often breaks... with no clear consistency.
Does anyone have a good solution to storing reference to local files in between user sessions? Do I have to use something like the HTML5 Filesystem API? Localstorage?
I may have missed what you are getting at, but it sounds like you just need a cookie. http://www.w3schools.com/js/js_cookies.asp
You can save whatever file name you want in a simple cookie and then the next time they visit the page you recall the video name they want.

Categories

Resources