Reading client side text file using Javascript - javascript

I want to read a file (on the client side) and get the content in an array. It will be just one file. I have the following and it doesn't work. 'query_list' is a textarea where I want to display the content of the file.
<input type="file" id="file" name="file" enctype="multipart/form-data"/>
<script>
document.getElementById('file').addEventListener('change', readFile, false);
function readFile (evt) {
var files = evt.target.files;
var file = files[0];
var fh = fopen(file, 0);
var str = "";
document.getElementById('query_list').textContent = str;
if(fh!=-1) {
length = flength(fh);
str = fread(fh, length);
fclose(fh);
}
document.getElementById('query_list').textContent = str;
}
</script>
How should I go about it? Eventually I want to loop over the array and run some SQL queries.

If you want to read files on the client using HTML5's FileReader, you must use Firefox, Chrome or IE 10+. If that is true, the following example reads a text file on the client.
your example attempts to use fopen that I have never heard of (on the client)
http://jsfiddle.net/k3j48zmt/
document.getElementById('file').addEventListener('change', readFile, false);
function readFile (evt) {
var files = evt.target.files;
var file = files[0];
var reader = new FileReader();
reader.onload = function(event) {
console.log(event.target.result);
}
reader.readAsText(file)
}
For IE<10 support you need to look into using an ActiveX Object like ADO.Stream Scripting.FileSystemObject http://msdn.microsoft.com/en-us/library/2z9ffy99(v=vs.85).aspx but you'll run into a security problem. If you run IE allowing all ActiveX objects (for your website), it should work.

There is such thing as HTML5 File API to access local files picked by user, without uploading them anywhere.
It is quite new feature, but supported by most of modern browsers.
I strongly recommend to check out this great article to see, how you can use it.
There is one problem with this, you can't read big files (~400 MB and larger) because straight forward FileAPI functions attempting to load entire file into memory.
If you need to read big files, or search something there, or navigate by line index check my LineNavigator, which allows you to read, navigate and search in files of any size. Try it in jsFiddle! It is super easy to use:
var navigator = new FileNavigator(file);
navigator.readSomeLines(0, function linesReadHandler(err, index, lines, eof, progress) {
// Some error
if (err) return;
// Process this line bucket
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
// Do something with it
}
// End of file
if (eof) return;
// Continue reading
navigator.readSomeLines(index + lines.length, linesReadHandler);
});

Well I got beat to the answer but its different:
<input type="file" id="fi" />
<button onclick="handleFile(); return false;">click</button>
function handleFile() {
var preview = document.getElementById('prv')
var file = document.getElementById('fi').files[0];
var div = document.body.appendChild(document.createElement("div"));
div.innerHTML = file.getAsText("utf-8");
}
This will work in FF 3.5 - 3.6, and that's it. FF 4 and WebKit you need to use the FileReader as mentioned by Juan Mendes.
For IE you may find a Flash solution.

I work there, but still wanted to contribute because it works well: You can use the filepicker.io read api to do exactly this. You can pass in an dom element and get the contents back, for text or binary data, even in IE8+

Related

Problem with reading large XML file into Javascript

I created a website where you can import an XML file and then read it out. It works perfectly fine for most files but I tried using an XML file with 730MB and it doesn't work anymore. I don't seem to be getting any errors on the console, but if I for example use this code,
numberOfReports = xmlDoc.getElementsByTagName("DailyReport").length;
I always get 0 even though it should be far more than that, since the XML files definetely contains multiple <DailyReport> elements. My function to import and parse the files looks like this:
// Function to import and serialize the XML file
function import_XML() {
var input = document.createElement('input');
input.type = 'file';
input.onchange = e => {
// getting a hold of the file reference
file = e.target.files[0];
// setting up the reader
var reader = new FileReader();
reader.readAsText(file, 'UTF-8');
// Tell the reader what to do when it's done reading
reader.onload = readerEvent => {
content = readerEvent.target.result;
const parser = new DOMParser();
xmlDoc = parser.parseFromString(content, "application/xml");
console.log(xmlDoc.documentElement.nodeName == "parsererror" ? "Error while parsing XML File" : xmlDoc.documentElement.nodeName);
console.log("content: " + content);
// Number of reports in the XML file
numberOfReports = xmlDoc.getElementsByTagName("DailyReport").length;
console.log("number of daily reports: " + numberOfReports);
updateTable();
}
}
input.click();
}
The content I get from content = readerEvent.target.result; in the console is also just empty:
I'm not sure if it's because the file is too large, but the XML file should not have any malformations. Can anyone help me with this problem? Would really appreciate any help!
I suspect you're exceeding the maximum string length of your browser's JavaScript engine. Different engines have different limits. MDN says Firefox's limit is about 1GB (although I just tried an experiment and it was more like 800MB). A quick experiment in Brave (Chrome-like) suggests a maximum of about 512MB:
let size = 0;
const chunk = "".padStart(4096, " ");
const max = 800 * 1024 * 1024;
try {
let str = "";
while (str.length < max) {
size = str.length;
str += chunk;
}
console.log(`worked! size = ${size / 1024 / 1024}`);
} catch {
console.log(`ERROR, size = ${size / 1024 / 1024}`);
}
The same experiment in Node.js (which uses the same JavaScript engine as Chromium-based browsers, V8) yields the same result, suggesting it's the limit in V8.
Unfortunately, DOMParser only accepts strings, not (say) blobs. I think you're probably not going to be able to handle files that large on V8-based browsers.
I suspect DOMParser will get a method that allows it to read streams someday, but that doesn't help you now. The only solution I can think of is to find an XML parser written in JavaScript that either supports streams or that you could adapt to use a stream. There are several XML parsers in npm packages, there might be one that can use a blob, or a ReadableStream, or one that supports Node.js streams you could adapt to work with ReadableStream (and the browser's version of XML documents rather than whatever they're using on Node.js).

Javascript - Download prompting of self created batch files

I"m a noob in javascript so I am sorry if my question is a simple one. anyway,
I'm writing a code that creates a batch file in order to open a certain file in the default application defined by the operation system. For example, pdf files will open in Adobe's Acrobat Reader. To do so, I'm using the FileSaver.js
And my code goes like this:
$(document).ready(function() {
$('#openPdf').click(function() {
saveAs(data2blob(
myPDF),
'openPDF.bat');
});
});
function data2blob(data, isBase64) {
var chars = "";
if (isBase64)
chars = atob(data);
else
chars = data;
var bytes = new Array(chars.length);
for (var i = 0; i < chars.length; i++)
bytes[i] = chars.charCodeAt(i);
var blob = new Blob([new Uint8Array(bytes)],
{type: "text/plain;charset=utf-8"});
return blob;
}
with myPDF being a string to a specific file I want to open which I'm certain of its existence. When I test my code on IE, it works perfectly. However, when I try it on Firefox, the file created is 'openPDF.bat.sdx' instead of 'openPDF.bat'. I've checked that it is indeed the same file only with the added extension. Does anyone have an idea what is the reason for this? and how can I overcome it?
I finally managed to download the file in Firefox the same way as in IE. I've made one minor change in the code: when creating the blob variable in the data2blob function I've used:
var blob = new Blob([new Uint8Array(bytes)], {type: "application/octet-stream"});
Not sure, what is the difference between the way it was before and how it is now, except of the result of course.

Web Development Displaying Local Files

Based on research, I've found tutorials, such as this one from Eric Bidelman, that go into FileReader usage. Instead of local files, these tutorials use files provided by the user. Modifying these examples to try and display local files were not successful.
After some research I've found that most browsers by default do not allow access to local files [1]. Some recommend using unsafe modes for testing, but that's not what I'm looking for as that would apply to only my testing [2].
Currently I allow the download of log files. My goal here with FileReader was to provide a way to view the files as well. Is there a way to achieve this? I'm coming up with blanks and have almost resigned to only allowing downloads instead of adding viewing. The following is example code of local file reading. This code fails since 'logpath' is not of type blob. I believe my question doesn't really require code, but I provided an example anyway.
HTML Code
<select name="loglist" id="loglist" onchange="run()" size="2">
<option>stack1.log</option>
<option>stack2.log</option>
</select>
Javascript
function run() {
var reader = new FileReader();
log = document.getElementById( "loglist" ).value;
var logdir = "/var/log/";
var logpath = logdir.concat(log);
reader.onload = function() {
logtext = reader.result;
alert(logtext);
}
reader.readAsText(logpath);
}
There is no way for JavaScript, embedded in a webpage, to access files on the user's local system other than through the File API when the user selects the file using a file input. It is not possible for the page to supply the file name to be opened.
var inp = document.querySelector("input");
inp.addEventListener("change", show);
function show(e) {
var f = this.files[0];
var r = new FileReader();
r.addEventListener("load", display);
r.readAsText(f);
function display(e) {
document.body.appendChild(
document.createTextNode(
e.target.result
)
);
}
}
<input type="file" id="input">

Javascript new File() gem file size

I have the following file structure:
test.html
test.json
And the following JS function:
function get_file(){
var app_path = app.activeDocument.path,
file = new File(app_path + '/test.json');
console.log(file);
}
How can I make the function log the file's content?
I'm not sure if everything you can do in the browsers environment translates to everything you can do in photoshops environment. But you should look at a few things.
Doing This in the Browser
The File object.
https://developer.mozilla.org/en-US/docs/Web/API/File
Notable that it extends the Blob object.
https://developer.mozilla.org/en-US/docs/Web/API/Blob
Which if you researched you would find it can be read using the FileReader.
https://developer.mozilla.org/en-US/docs/Web/API/FileReader
So this would work in the browser but may/may-not work in the photoshop scripting set.
function get_file(){
var app_path = app.activeDocument.path,
file = new File(app_path + '/test.json');
var reader = new FileReader();
reader.onloadend = function() {
console.log(reader.result);
}
reader.readAsText(file);
}
This is asynchronous so you may need to use a callback depending on what you're trying to do with this. You won't be able to return the string from inside the reader.onloadend event.
Doing This in Photoshop
Take a look at their scripting references. Specifically the javascript reference.
All Resources: http://www.adobe.com/devnet/photoshop/scripting.html
Javascript PDF: http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/photoshop/pdfs/photoshop-cc-javascript-ref-2015.pdf
It looks like they don't have the FileReader but instead the File object can be used to read content. The File API begins on page 109 but it's empty! The documentation is a bit pathetic so I can see why you'd have trouble finding this. With some searching I found someone doing this in 2012 (but I don't know if it will still work- worth a shot)
var b = new File("c:\test.txt");
b.open('r');
var str = "";
while(!b.eof) {
str += b.readln();
}
b.close();
alert(str);
Let me know if that works.

playing html5 video from in memory source

I am retrieving multiple encrypted data with the help of some ajax queries, and performing some manipulation to transform all theses encrypted chunks into a valid video. And now that I have the binary of the video in memory, I am stuck. How can I display it ?
Just to be sure, I have replicated all theses steps on the server side, and the final output is really a playable video. So my only problem is to display my javascript binary object as a video.
I am doing my best to use only web technologies (html5, video tag, javascript) and I would like to avoid developing my own custom player in flash, which is my very last solution.
if you have an idea, I'm interested. For my part, I am out of imagination.
Here's a quick example that just uses a file input instead of the AJAX you'd normally be using. Note that the first input is wired up to a function that will read the file and return a dataURL for it.
However, since you don't have a fileObject, but instead have a stream of data that represents the contents of the file, you can't use this method. So, I've included a second input, which is wired up to a function that just loads the file as a binary string. This string is then base64 encoded 'manually' with a browser function, before being turned into a dataURL. To do this,you need to know what type of file you're dealing with in order to construct the URL correctly.
It's fairly slow to load even on this laptop i7 and probably sucks memory like no-one's business - mobile phones will likely fall over in a stupor (I haven't tested with one)
You should be able to get your data-stream and continue on from the point where I have the raw data (var rawResult = evt.target.result;)
Error checking is left as an exercise for the reader.
<!DOCTYPE html>
<html>
<head>
<script>
"use strict";
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function byId(id,parent){return (parent == undefined ? document : parent).getElementById(id);}
// callback gets data via the .target.result field of the param passed to it.
function loadFileObject(fileObj, loadedCallback)
{
var reader = new FileReader();
reader.onload = loadedCallback;
reader.readAsDataURL( fileObj );
}
// callback gets data via the .target.result field of the param passed to it.
function loadFileAsBinary(fileObj, loadedCallback)
{
var reader = new FileReader();
reader.onload = loadedCallback;
reader.readAsBinaryString( fileObj );
}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded()
{
byId('fileInput1').addEventListener('change', onFileInput1Changed, false);
byId('fileInput2').addEventListener('change', onFileInput2Changed, false);
}
function onFileInput1Changed(evt)
{
if (this.files.length != 0)
{
var curFile = this.files[0];
loadFileObject(curFile, onVideoFileReadAsURL);
function onVideoFileReadAsURL(evt)
{
byId('vidTgt').src = evt.target.result;
byId('vidTgt').play();
}
}
}
function onFileInput2Changed(evt)
{
if (this.files.length != 0)
{
var curFile = this.files[0];
loadFileAsBinary(curFile, onVideoFileReadAsBinary);
function onVideoFileReadAsBinary(evt)
{
var rawResult = evt.target.result;
var b64Result = btoa(rawResult);
var prefaceString = "data:" + curFile.type + ";base64,";
// byId('vidTgt').src = "data:video/mp4;base64," + b64Result;
byId('vidTgt').src = prefaceString + b64Result;
byId('vidTgt').play();
}
}
}
</script>
<style>
</style>
</head>
<body>
<input type='file' id='fileInput1'/>
<input type='file' id='fileInput2'/>
<video id='vidTgt' src='vid/The Running Man.mp4'/>
</body>
</html>
To display your video you would need to get an URL for it so that you are able to pass a reference to the video element.
There is URL.createObjectURL which should provide you with such an URL to refer to your data. See https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL for further explanations and mind the compatibility table.
Mozilla hosts an example at https://developer.mozilla.org/samples/domref/file-click-demo.html which displays local files. It should be possible to adapt this to setting the video element's src property instead. Depending on how you store your data, it should be possible to play your video this way.
I tried it in Firefox for data from a File object which left me with a URL blob:https://developer.mozilla.org/ed2e4f2f-57a6-4b06-8d56-d0a1a47a9ffd that I could use to play a video.

Categories

Resources