Access local file with html5 FileReader - javascript

I'm trying to make an offline app that reads text from a text file that is stored locally. I understand this is possible with html5 and FileReader. I want to hard-code the relative path. I have read the docs and all them them are based on an array of FileList. But since I am just doing one file with a static path, I can't make sense of it. This is silly, I know, but what I have so far:
var file = "data/data";
var reader = new FileReader();
reader.readAsText(file);
alert(reader.String);

The FileReader API lets you read files selected by the user in a file input.
It does not let the author of a webpage choose files from their visitor's systems to read. That would be a security risk.

This is possible using ActiveX, which isn't too hard to do if you've never worked with it. Check this out for more info: http://msdn.microsoft.com/en-us/library/2z9ffy99(v=vs.84).aspx
Just means the user will probably have to agree to let ActiveX run.. which admittedly might scare a few away. So it depends upon how much you actually need it.

Related

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.

Why can't I embed a PDF from my local machine on my website?

I'm working on a website where the users can solve a practice exam.
My client wants to include a div next to the exam with a PDF viewer.
The idea is that the user can select a PDF file from his local machine and it will be loaded into the PDF viewer next to the exam.
I made it work using pdf.js and pdfobject.
The problem is that both options require the PDF file to be uploaded to our server.
Due to intellectual property law, that is unacceptable to our client.
They want the PDF file to be embeded without uploading it to our server. So it has to be loaded directly from the user's machine.
I found that it can't be done. All the plugins I tried require a virtual url, and will not accept a physic one (file:///local/path/file.pdf).
I don't want to just tell my client "it can't be done". I would like to know a technical explanation of why can't it be done.
If somebody knows a way to make it work it would be better!
This is a security policy. Issues it defends against include:
Allowing sites to detect your operating system by checking default installation paths
Allowing sites to exploit system vulnerabilities (e.g., C:\con\con in Windows 95/98)
Allowing sites to detect browser preferences or read sensitive data
Try to load it in a <iframe> with the URL of the PDF as src. But it might fail because of the client's browser's security policy. So this is brittle at best.
Maybe you can use HTML5 localstorage to upload the file to a "safe" location ("safe" as far as the browser is concerned).
PDFJS.getDocument() supports "a typed array (Uint8Array)
already populated with data or parameter object." So upload to local storage, get the document as bytes from there and then pass it to pdf.js.
Related:
https://hacks.mozilla.org/2012/02/saving-images-and-files-in-localstorage/
You might be able to do this, if the browser supports it. Take a look at the FileReader object. If the user's browser supports that, you can allow the user to select a file and reference that file in code. Something like this works for me in Firefox:
$('input[type=file]').change(function () {
if (window.FileReader) {
var input = this;
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$(input).next('iframe').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
});
So if you have a input type="file" followed by an iframe then this will allow the user to select the file, and once it's selected it will load it into the iframe as a base64-encoded data URI.
Example here.

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

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