maintaining reference to client files between sessions - javascript

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.

Related

How do I save file urls on javascript?

I'm creating a webapp on which I load and display images.
I want to have a feature on which the user can save the images they loaded so they can reload them on future sessions without having to manually set up everything again.
For doing this I have thought of storing the url from the files, but it looks like I can't access the url of files because of security on most browsers. Is there anything I can do to save the url of the files, or something similar so I can reload the files on future sessions?
It will ideally allow to store many files, so saving the local paths to the images is best so it doesn't consume much space.
For the app I'm using angular and tauri.
Anyone can help? Thanks a lot in advance!
EDIT: I found out there is a way to do this on tauri with the dialog module you can find here: https://tauri.studio/api/js/modules/dialog more info here:https://github.com/tauri-apps/wry/issues/87
If anyone reads this and is using electron instead of tauri I've read that the File Object gets added a path property, so you can get it from there.
Thanks everyone for the help!
For storing user-downloaded images, you need a backend. If you don't want to run one, you can try to store images as data: urls in cookies or local storage, but it won't work well.
I recently did one functionality for download file and sharing the code here
downloadFile(data, fileName) {
const urlBlob = window.URL.createObjectURL(data);
const link = document.createElement('a');
link.href = urlBlob;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
Data stands for your file path or file URL and
fileName stands for File save with name as
you want
Found the answer!
I found out there is a way to do this on tauri with the dialog module you can find here: https://tauri.studio/api/js/modules/dialog more info here:https://github.com/tauri-apps/wry/issues/87
If anyone reads this and is using electron instead of tauri I've read that the File Object gets added a path property, so you can get it from there.
You can use cookies to store data. Users can block or remove cookies, but most users (as most users use Chrome) have cookies enabled by default.
You can store a cookie by doing
document.imageurl = "http://example.com";
and access it using
console.log(document.imageurl);
or something similar (variable is stored at document.imageurl)
The variable will stay there when the page is reloaded.

With offline file:/// protocol, I'm trying to store data in local storage through an iframe. How can I make this work, or is there a better way?

Background
In our company, we install our offline documentation topics (thousands of .htm files in a folder) on our users' computers. Users view our documentation offline through their browser using the file:/// protocol.
I have a banner that appears in the footer of each .htm file that asks users to decide whether we can track user analytics (via Application Insights). Once they make their choice, we don't show the banner.
My Goal and Overall Problem
My goal is to store their choice in the browser's local storage. I can do that just fine, but the problem is this:
These are offline .htm files. There is no website domain. So, the key and value for any local storage is stored only for the .htm file they are on at the time they make their choice. If they come back to a topic they made their choice on, then yes, my script can retrieve their choice. But if they navigate to another topic in our documentation system (another .htm file), the local storage key and value don't persist to those other topics, and my script doesn't know what they chose--so then the banner pops up again.
My Workaround Idea
I doubt this is the best approach, but not having a lot of experience and not knowing what else to try, necessity becomes the mother of invention.
Here's what I'm trying:
Have my local storage requests go through a single .htm file called storage.htm, thereby getting around the above problem by always having a single point of contact (storage.htm) with the local storage.
storage.htm loads via a blank iframe.
The iframe is tacked onto each .htm topic.
When a topic .htm loads, the iframe also loads and any functions inside it become (hopefully) available for use by my main script.
When users click on the banner, I send the choice as query parameters through my main script to the iframe's src.
storage.htm contains a parseQuery() function, and inside that function, it parses any query params and then does the actual localStorage.getValue(key) and localStorage.setValue(key,value) requests.
I then want to somehow force the iframe to refresh with those parameters and then call the parseQuery() function there from my main script.
My Code
From my main script:
Attempt 1:
I've tried the top-voted item from this thread,
How to check if iframe is loaded or it has a content?
but I get stuck inside the checkIfFrameLoaded() function, and it continues to loop through the check to see if the iframe is loaded. It never loads. I think it's because the contentWindow and/or contentDocument don't work with my offline files, so I won't bore you with that code.
Attempt 2:
This is what I'd like to do as it seems cleaner:
function doIframeStorage(type,key,value){
// We get a handle on the iframe's id of 'storage'.
let storage = document.querySelector('#storage');
const src = storage.getAttribute('src');
let query = src;
if (type==='get'){
query = src + `?type=${type}&key=${key}`;
} else if (type==='set'){
query = src + `?type=${type}&key=${key}&value=${value}`;
}
storage.src = query;
storage.addEventListener('load', (e) => parseQuery());
}
But I'm running into a problem where my parseQuery() function (from storage.htm) is always undefined:
Uncaught ReferenceError: parseQuery is not defined
Is it possible to load and access my parseQuery() function from my main script like I'm doing? If so, how? I thought the addEventListener would ensure it was loaded and therefore the parseQuery() function would then be available.
Or Is there a better way to do what I'm attempting?

Keeping information about js file in localStorage

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);

Is It Possibly to Access Firefox Save As Command Using JS?

I'm trying to figure out how to call the File Save As Command in Firefox
(the one you get when you right click an image and save it) to save an image using JS (or if there is something else I can use, I would be grateful if you pointed me in that direction). I am looking for an example of how to open the Save As menu and pre-fill the file name field ... I've been searching furiously and have come up with zip. In my search I saw that you cannot directly save a file to disk, but is it impossible to call the save as function? Any suggestions would be greatly appreciated!
Edit:
I'm not looking to make this code available to everyone, and the java script is client side, I'm just writing a small script to make saving photos a little easier in terms of naming them.
-Will
No you can't do this, and really you are trying to find a solution in a way that does not embrace the internet and the way people interact with content. What you are trying to do is call on Operating System operation from Javascript. If there were anyway this would be possible, I don't think it is at all, it would be a very poor solution. Think about all the different Operating Systems Firefox is being used on. If you found a solution for Windows 7, what about an Apple Mac running Firefox?
What you should consider is that a User decides whether to Save something to their computer, not the programmer of the application. Provide a link to the file, most users know how to right click a link and select Save As. Add help tip explaining what to do as well.
To give a File a specific name or even start an automatic download when a User clicks or takes some kind of action, you can create a response from your server that is a PDF,Excel,Jpeg,Doc,Docx or many other files types. The server can load the file in memory and sent it as a response with the proper header information in the response.
For example to set a specific name for the file when the user downloads you can set your Response header with something like:
header('Content-Disposition: attachment; filename="downloaded.pdf"');
You can use the anchor element's download attribute to specify that a link is to be downloaded. Note that this is not implemented in all browsers, Chrome, Firefox, and Opera currently support it
https://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
HTMLAnchorElement.download
Is a DOMString indicating that the linked
resource is intended to be downloaded rather than displayed in the
browser. The value represent the proposed name of the file. If the
name is not a valid filename of the underlying OS, browser will adapt
it. The value is a URL with a scheme like http:, file:, data: or even
blob: (created with URL.createObjectURL).
Demo
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillRect(25,25,100,100);
ctx.clearRect(45,45,60,60);
ctx.strokeRect(50,50,50,50);
var link = document.getElementById("link");
//Set href to the data url that you want downloaded
link.href = "http://placehold.it/350x350";
//set download to the default filename you want to use
link.download = "image.png";
<canvas id="canvas" width="150" height="150"></canvas>
Click to download
You can also specify a regular url to a file, but note that if the server sends a filename header: Content-Disposition ... filename... that it will overwrite whatever you have in the download attribute.

FakePath issue in Chrome browser

I am making a browser based audio player. So for making a playlist from the local directory I am using :
<input type="file" id="getFile" />
Then I am using a button to confirm the playlist.On clicking the button I am calling a javascript function to change the src of the audio tag to play the new audio file selected in the playlist. I want the exact path of the file from the input file to run in the HTML5 audio player but it starts taking the path as C://Fakepath/filename.mp3. Can someone help me with this.
This is a security feature, by design. You should not be able to read the original file path of a file input into a browser form. File input is for reading file contents only, not metadata like path on the user's file system.
The good news is that you don't need the original file path. You can use FileReader's readAsDataURL to convert the file contents into a base64-encoded data URL and use that as the audio src. To read from #myUploadInput and output through #myAudioElement (also available as a working fiddle):
var reader = new FileReader();
reader.onload = function (event) {
document.getElementById("myAudioElement").src = event.target.result;
};
reader.readAsDataURL(document.getElementById("myUploadInput").files[0]);
if the user is 'building' / creating the playlist based on files they have locally you could do a 'browse' field (s) where they select the local audio files, then take the contents of the field (that Should include the paths to those images), build an array of the count/id, filename.mp3, and path... then, based on what is 'chosen' to play, just reassemble the full local path and play that file.
that would be an approach I would take anyway to see if it would work. the necessary piece here is getting the user to disclose the paths to the audio files... but Im still not 100% sure it would work given the security feature that the earlier commenter posted a link to.
if this were included in an application the user approved for local installation you could just refer to it using the 'application directory' and copy the file to that 'safe location' but since its web based it just really opens up a whole can of worms in terms of a potentially unapproved / authorized web function knowing your local directory structure. good luck, let me know if you find a solution.

Categories

Resources