简体   繁体   中英

Read local XML with JS

At the moment, due to the security policy Chromium can not read local files via ajax without --allow-file-access-from-files . But I currently need to create a web application where the database is a xml-file (in the extreme case, json), located in one dir with index.html. It is understood that the user can run this application locally. Are there workarounds for reading xml- (json-) file, without wrapping it in a function and change to js extension?

loadXMLFile('./file.xml').then(xml => {
    // working with xml
});

function loadXMLFile(filename) {
    return new Promise(function(resolve, reject) {
        if('ActiveXObject' in window) {
            // If is IE
            var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
            xmlDoc.async = false;
            xmlDoc.load(filename);

            resolve(xmlDoc.xml);
        } else {
            /*
             * how to read xml file if is not IE?
             * ...
             * resolve(something);
             */
        }

    }
}

Accessing file: protocol at chromium using XMLHttpRequest() or <link> element without --allow-file-access-from-files flag set at chromium instance launch is not enabled by default.

--allow-file-access-from-files

By default, file:// URIs cannot read other file:// URIs. This is an override for developers who need the old behavior for testing.


At the moment, due to the security policy Chromium can not read local files via ajax without --allow-file-access-from-files . But I currently need to create a web application where the database is a xml-file (in the extreme case, json), located in one dir with index.html. It is understood that the user can run this application locally. Are there workarounds for reading xml- (json-) file, without wrapping it in a function and change to js extension?

If user is aware that local files are to be used by the application you can utilize <input type="file"> element for user to upload file from user local filesystem, process file using FileReader , then proceed with application.

Else, advise user that use of application requires launching chromium with --allow-file-access-from-files flag set, which can be done by creating a launcher for this purpose, specifying a different user data directory for the instance of chromium. The launcher could be, for example

/usr/bin/chromium-browser --user-data-dir="/home/user/.config/chromium-temp" --allow-file-access-from-files

See also How do I make the Google Chrome flag “--allow-file-access-from-files” permanent?

The above command could also be run at terminal

$ /usr/bin/chromium-browser --user-data-dir="/home/user/.config/chromium-temp" --allow-file-access-from-files

without creating a desktop launcher; where when the instance of chromium is closed run

$ rm -rf /home/user/.config/chromium-temp

to remove the configuration folder for the instance of chromium.

Once the flag is set, user can include <link> element with rel="import" attribute and href pointing to local file and type set to "application/xml" , for option other than XMLHttpRequest to get file. Access XML document using

const doc = document.querySelector("link[rel=import]").import;

See Is there a way to know if a link/script is still pending or has it failed .


Another alternative, though more involved, would be to use requestFileSystem to to store the file at LocalFileSystem .

See

Or create or modify a chrome app and use

chrome.fileSystem

See GoogleChrome/chrome-app-samples/filesystem-access .


The simplest approach would be to provide a means for file upload by affirmative user action; process the uploaded file, then proceed with the application.

 const reader = new FileReader; const parser = new DOMParser; const startApp = function startApp(xml) { return Promise.resolve(xml || doc) }; const fileUpload = document.getElementById("fileupload"); const label = document.querySelector("label[for=fileupload]"); const handleAppStart = function handleStartApp(xml) { console.log("xml document:", xml); label.innerHTML = currentFileName + " successfully uploaded"; // do app stuff } const handleError = function handleError(err) { console.error(err) } let doc; let currentFileName; reader.addEventListener("loadend", handleFileRead); reader.addEventListener("error", handleError); function handleFileRead(event) { label.innerHTML = ""; currentFileName = ""; try { doc = parser.parseFromString(reader.result, "application/xml"); fileUpload.value = ""; startApp(doc) .then(function(data) { handleAppStart(data) }) .catch(handleError); } catch (e) { handleError(e); } } function handleFileUpload(event) { let file = fileUpload.files[0]; if (/xml/.test(file.type)) { reader.readAsText(file); currentFileName = file.name; } } fileUpload.addEventListener("change", handleFileUpload) 
 <input type="file" name="fileupload" id="fileupload" accept=".xml" /> <label for="fileupload"></label> 

use document.implementation.createDocument("", "", null)

instead of new ActiveXObject('Microsoft.XMLDOM') .

You can find the API through GOOGLE. Good luck.

If I understand correctly, the deliverable is intended to run locally so you will not be able to set any flags for local file access on a user's machine. Something I've done in a pinch is to pack it up as an executable with something like nw.js and keep the external data files. Otherwise, you're probably looking at loading as script using a JSON schema in a JS file.

I had a similar problem before. I solved by simply embedding the XML file into the HTML using PHP. Since the application is loaded locally from disk, size, cache etc. are not a concern.

If you're using Webpack, you can instead directly import the file using a loader like this or this , in which case the file is included into the resulting bundled javascript.

You can load XML through a string of text using DOMParser , Just load your file and parse the text using the .parseFromString . You could use an if statement containing (window.DOMParser) to check if the DOMParser is supported

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM