0

I am working on a completely locally run web app which is to be run without any network connection. The idea is to distribute a pack to users (~40) who will use the app to basically fill in bunch of form fields and charts. As changes are made to the page an object with data in JSON format is filled in. I have the page working well now and I have a function to load an existing JSON file and populate any fields that are present in the file. The idea behind this is that someone can be "halfway" through filling out the fields in the app or someone can load up previous work.

My question here is; what is the best system available to get data from a webpage into JSON file and be able to save that to local machine so that it can be distributed (emailed, saved to SP, network drive, access db etc etc) at a later date? The scenario under which the app will be used is a strictly no network access area so this is why I need to be able save and access a file locally. I have a half-solution where I can open a separate tab which has the contents of the file but I really would prefer to have the downloading/saving prompting done for me as most users won't go further than seeing a page with gibberish on it.

the code I have to accomplish this much is:

//Download file
function SaveToDisk() {
    var data = JSON.stringify(currentSession);
    var fileURL = 'data:text/json;charset=utf8,' + encodeURIComponent(data);
    var fileName = $('file-save').val();
    console.log(fileURL);

    // for non-IE
    if (!window.ActiveXObject) {
        var save = document.createElement('a');
        save.href = fileURL;
        save.target = '_blank';
        save.download = fileName || 'unknown';

        var event = document.createEvent('Event');
        event.initEvent('click', true, true);
        save.dispatchEvent(event);
        (window.URL || window.webkitURL).revokeObjectURL(save.href);
    }

    // for IE
    else if ( !! window.ActiveXObject && document.execCommand)     {
        var _window = window.open(fileURL, '_blank');
        _window.document.close();
        _window.document.execCommand('SaveAs', true, fileName || fileURL)
        _window.close();
    }
}

currentSession object looks like:

//Global JSON variables
var currentSession = {
    "sections":{
        "header":{
            "tool":"",
            "subsystem":"",
            "engineer":"",
            "date":"",
            "so":""

        },
        "whys":{
            "why1":{
                "error":"",
                object:"",
                norm:"",
            },
            why2:{
                error:"",
                object:"",
                norm:"",
            },
            why3:{
                error:"",
                object:"",
                norm:"",
            },
            why4:{
                error:"",
                object:"",
                norm:"",
            },
            why5:{
                error:"",
                object:"",
                norm:"",
            }
        },
        probDescription:{
            "F":{
                "is":"",
                "isnot":""
            },
            "O":{
                "is":"",
                "isnot":""
            },
            "T":{
                "is":"",
                "isnot":""
            },
            "L":{
                "is":"",
                "isnot":""
            },
            "P":"",
            "W":"",
            "Pos":"",
            "S":""
        },
        possibleCauses :{
            "data":""
        },
        notes: ""
    }
};

UPDATE: Attempting this on windows machine (up to now been testing on mac) on IE9 gives the following error:

SCRIPT5007: Unable to get value of the property 'document': object is null or undefined

at the following line of the above code:

        _window.document.close();

Checking up on the line before:

    // for IE
    else if ( !! window.ActiveXObject && document.execCommand)     {

shows me that the if statement checks if activeXObject is present (only in IE???) and something else (div editable???) is true then it goes with the IE solution.

Then it creates a new window with the data url, (not sure what '_blank' is here) and attempts to save the file. So why is it erroring on the _window.document line? It does open a new window with the URL as:

data:application/octet-stream;{data} 

Any help here also greatly appreciated(and needed)

All help and suggestions gladly welcomed as I am rather new to all this and still learning.

Thx in advance

Martin O Leary
  • 633
  • 2
  • 10
  • 29
  • You could install local PHP server(WAMP, etc) and use `json_encode` and `file_put_contents` to save the data locally. It would also give you a lot of power to manipulate data more efficiently than entirely in JS. – Andrew Coder Oct 09 '15 at 22:02
  • At this link, http://www.html5rocks.com/en/tutorials/offline/storage/, you find a few "local storage solution" and their pros/cons, which you can compare, to find the best way for your app. – Asons Oct 09 '15 at 22:07
  • Possible duplicate of [How to create a dynamic file + link for download in Javascript?](http://stackoverflow.com/questions/8310657/how-to-create-a-dynamic-file-link-for-download-in-javascript) – CBroe Oct 10 '15 at 00:00
  • I looked at that but cannot get it working so assumed it was not suitable in my case - how could I apply that to my current case? put the jquery at the start of the HTML body and then use a button to 'click' the link? – Martin O Leary Oct 10 '15 at 08:34
  • @AndrewCoder are there any portable, lightweight non-admin rights requiring web servers available that can be distributed easily? I googled this today, I'm not sure what exactly I'm looking for but couldn't find anything that met that criteria. Can you suggest something? Cheers – Martin O Leary Oct 11 '15 at 01:43
  • Look into http://zwamp.sourceforge.net/ or WAMP. Google around, I'm sure you could find something. – Andrew Coder Oct 12 '15 at 15:08

2 Answers2

2

To force the download/saving prompt you can change the MIME type to application/octet-stream. The MIME type won't be saved to disk, so you don't have to worry about that later on. The second line in the function should therefore read:

var fileURL = 'data:application/octetstream;charset=utf8,' +  encodeURIComponent(data);

Of course there are good reasons that this local saving procedure can not be completely automated. Otherwise viruses could be easily distributed.

If you want to access the file later to distribute it via email, the local storage solutions in html5 do not really help.

sauerburger
  • 4,569
  • 4
  • 31
  • 42
  • do I change `var fileURL = 'data:text/json;charset=utf8,' + encodeURIComponent(data);` to `var fileURL = 'data:application/octet-stream;charset=utf8,' + encodeURIComponent(data);` ?? – Martin O Leary Oct 10 '15 at 07:43
  • yes, I think you have to leave out the charset, because binary data is not supposed to be encoded: `var fileURL = 'data:application/octet-stream;' + encodeURIComponent(data);` – sauerburger Oct 10 '15 at 09:34
  • charset is actually fine: `here` works. The down side is that afaik you can not set the file name. – sauerburger Oct 10 '15 at 10:13
0

Since I work mostly on IE9 and can guarantee that the users will use this I found this answer solved my issue:

https://stackoverflow.com/a/6106417/1770604

I have it implemented like so:

//Make file for attaching to mail
function makefile () {

    var fso = new ActiveXObject("Scripting.FileSystemObject"),
        FName = $('#file-save').val() + ".json",
        data = JSON.stringify(currentSession),
        thefile=fso.CreateTextFile("C:\\temp\\" + FName,true);

    thefile.Write(data);
    thefile.Close();
    alert("File created and saved to C:/temp/directory");
}

I have searched as much as possible and to my limited knowledge there are only two solutions to this without using a separate server:

  1. ActiveXObject in IE9 which allows the user to interact with the file system and write to a file in a specified dir - from what i've read this is not a very secure solution however this is my only real option.

  2. Some form of local/portable web server which can be distributed and started without user needing to do anything - I haven't been able to find the answer to this question yet so will keep looking but consider the question answered for now as long as you use IE9.

Community
  • 1
  • 1
Martin O Leary
  • 633
  • 2
  • 10
  • 29