Test browser:
Version of Chrome: 52.0.2743.116
It is a simple javascript that is to open an image file from local like 'C:\002.jpg'
function run(){
var URL = "file:///C:\002.jpg";
window.open(URL, null);
}
run();
Here is my sample code.
https://fiddle.jshell.net/q326vLya/3/
Please give me any suitable suggestions.
We use Chrome a lot in the classroom and it is a must to working with local files.
What we have been using is "Web Server for Chrome". You start it up, choose the folder wishing to work with and go to URL (like 127.0.0.1:port you chose)
It is a simple server and cannot use PHP but for simple work, might be your solution:
https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb
1)
Open your terminal and type
npm install -g http-server
2)
Go to the root folder that you want to serve you files and type:
http-server ./
3)
Read the output of the terminal, something kinda http://localhost:8080 will appear.
Everything on there will be allowed to be got.
Example:
background: url('http://localhost:8080/waw.png');
Okay folks, I completely understand the security reasons behind this error message, but sometimes, we do need a workaround... and here's mine. It uses ASP.Net (rather than JavaScript, which this question was based on) but it'll hopefully be useful to someone.
Our in-house app has a webpage where users can create a list of shortcuts to useful files spread throughout our network. When they click on one of these shortcuts, we want to open these files... but of course, Chrome's error prevents this.
This webpage uses AngularJS 1.x to list the various shortcuts.
Originally, my webpage was attempting to directly create an <a href..> element pointing at the files, but this produced the "Not allowed to load local resource" error when a user clicked on one of these links.
<div ng-repeat='sc in listOfShortcuts' id="{{sc.ShtCut_ID}}" class="cssOneShortcutRecord" >
<div class="cssShortcutIcon">
<img ng-src="{{ GetIconName(sc.ShtCut_PathFilename); }}">
</div>
<div class="cssShortcutName">
<a ng-href="{{ sc.ShtCut_PathFilename }}" ng-attr-title="{{sc.ShtCut_Tooltip}}" target="_blank" >{{ sc.ShtCut_Name }}</a>
</div>
</div>
The solution was to replace those <a href..> elements with this code, to call a function in my Angular controller...
<div ng-click="OpenAnExternalFile(sc.ShtCut_PathFilename);" >
{{ sc.ShtCut_Name }}
</div>
The function itself is very simple...
$scope.OpenAnExternalFile = function (filename) {
//
// Open an external file (i.e. a file which ISN'T in our IIS folder)
// To do this, we get an ASP.Net Handler to manually load the file,
// then return it's contents in a Response.
//
var URL = '/Handlers/DownloadExternalFile.ashx?filename=' + encodeURIComponent(filename);
window.open(URL);
}
And in my ASP.Net project, I added a Handler file called DownloadExternalFile.aspx which contained this code:
namespace MikesProject.Handlers
{
/// <summary>
/// Summary description for DownloadExternalFile
/// </summary>
public class DownloadExternalFile : IHttpHandler
{
// We can't directly open a network file using Javascript, eg
// window.open("\\SomeNetworkPath\ExcelFile\MikesExcelFile.xls");
//
// Instead, we need to get Javascript to call this groovy helper class which loads such a file, then sends it to the stream.
// window.open("/Handlers/DownloadExternalFile.ashx?filename=//SomeNetworkPath/ExcelFile/MikesExcelFile.xls");
//
public void ProcessRequest(HttpContext context)
{
string pathAndFilename = context.Request["filename"]; // eg "\\SomeNetworkPath\ExcelFile\MikesExcelFile.xls"
string filename = System.IO.Path.GetFileName(pathAndFilename); // eg "MikesExcelFile.xls"
context.Response.ClearContent();
WebClient webClient = new WebClient();
using (Stream stream = webClient.OpenRead(pathAndFilename))
{
// Process image...
byte[] data1 = new byte[stream.Length];
stream.Read(data1, 0, data1.Length);
context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", filename));
context.Response.BinaryWrite(data1);
context.Response.Flush();
context.Response.SuppressContent = true;
context.ApplicationInstance.CompleteRequest();
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
And that's it.
Now, when a user clicks on one of my Shortcut links, it calls the OpenAnExternalFile function, which opens this .ashx file, passing it the path+filename of the file we want to open.
This Handler code loads the file, then passes it's contents back in the HTTP response.
And, job done, the webpage opens the external file.
Phew ! Again - there is a reason why Chrome throws this "Not allowed to load local resources" exception, so tread carefully with this... but I'm posting this code just to demonstrate that this is a fairly simple way around this limitation.
Just one last comment: the original question wanted to open the file "C:\002.jpg". You can't do this. Your website will sit on one server (with it's own C: drive) and has no direct access to your user's own C: drive. So the best you can do is use code like mine to access files somewhere on a network drive.
Chrome specifically blocks local file access this way for security reasons.
Here's an article to workaround the flag in Chrome (and open your system up to vulnerabilities):
http://www.chrome-allow-file-access-from-file.com/
There is a workaround using Web Server for Chrome. Here are the steps:
Add the Extension to chrome.
Choose the folder (C:\images) and launch the server
on your desired port.
Now easily access your local file:
function run(){
// 8887 is the port number you have launched your serve
var URL = "http://127.0.0.1:8887/002.jpg";
window.open(URL, null);
}
run();
PS: You might need to select the CORS Header option from advanced setting incase you face any cross origin access error.
This issue come when I am using PHP as server side language and the work around was to generate base64 enconding of my image before sending the result to client
$path = 'E:/pat/rwanda.png';
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = file_get_contents($path);
$base64 = 'data:image/' . $type . ';base64,' . base64_encode($data);
I think may give someone idea to create his own work around
Thanks
Google Chrome does not allow to load local resources because of the security. Chrome need http url. Internet Explorer and Edge allows to load local resources, but Safari, Chrome, and Firefox doesn't allows to load local resources.
Go to file location and start the Python Server from there.
python -m SimpleHttpServer
then put that url into function:
function run(){
var URL = "http://172.271.1.20:8000/" /* http://0.0.0.0:8000/ or http://127.0.0.1:8000/; */
window.open(URL, null);
}
If you have php installed - you can use built-in server. Just open target dir with files and run
php -S localhost:8001
If you could do this, it will represent a big security problem, as you can access your filesystem, and potentially act on the data available there... Luckily it's not possible to do what you're trying to do.
If you need local resources to be accessed, you can try to start a web server on your machine, and in this case your method will work. Other workarounds are possible, such as acting on Chrome settings, but I always prefer the clean way, installing a local web server, maybe on a different port (no, it's not so difficult!).
See also:
Open local files(file://) using Chrome
Opening local files from chrome
You just need to replace all image network paths to byte strings in stored Encoded HTML string.
For this you required HtmlAgilityPack to convert Html string to Html document.
https://www.nuget.org/packages/HtmlAgilityPack
Find Below code to convert each image src network path(or local path) to byte sting.
It will definitely display all images with network path(or local path) in IE,chrome and firefox.
string encodedHtmlString = Emailmodel.DtEmailFields.Rows[0]["Body"].ToString();
// Decode the encoded string.
StringWriter myWriter = new StringWriter();
HttpUtility.HtmlDecode(encodedHtmlString, myWriter);
string DecodedHtmlString = myWriter.ToString();
//find and replace each img src with byte string
HtmlDocument document = new HtmlDocument();
document.LoadHtml(DecodedHtmlString);
document.DocumentNode.Descendants("img")
.Where(e =>
{
string src = e.GetAttributeValue("src", null) ?? "";
return !string.IsNullOrEmpty(src);//&& src.StartsWith("data:image");
})
.ToList()
.ForEach(x =>
{
string currentSrcValue = x.GetAttributeValue("src", null);
string filePath = Path.GetDirectoryName(currentSrcValue) + "\\";
string filename = Path.GetFileName(currentSrcValue);
string contenttype = "image/" + Path.GetExtension(filename).Replace(".", "");
FileStream fs = new FileStream(filePath + filename, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
br.Close();
fs.Close();
x.SetAttributeValue("src", "data:" + contenttype + ";base64," + Convert.ToBase64String(bytes));
});
string result = document.DocumentNode.OuterHtml;
//Encode HTML string
string myEncodedString = HttpUtility.HtmlEncode(result);
Emailmodel.DtEmailFields.Rows[0]["Body"] = myEncodedString;
Chrome and other Browser restrict the access of a server to local files due to security reasons. However you can open the browser in allowed access mode. Just open the terminal and go to the folder where chrome.exe is stored and write the following command.
chrome.exe --allow-file-access-from-files
Read this for more details
This way, However, didn't work for me so I made a different route for every file in a particular directory. Therefore, going to that path meant opening that file.
function getroutes(list){
list.forEach(function(element) {
app.get("/"+ element, function(req, res) {
res.sendFile(__dirname + "/public/extracted/" + element);
});
});
}
I called this function passing the list of filename in the directory __dirname/public/extracted and it created a different route for each filename which I was able to render on server side.
This is for google-chrome-extension
const url = "file:///C:\002.jpg"
chrome.tabs.create({url, active:true})
manifest.json
{
"name": "",
"manifest_version": 3,
"permissions": [
"activeTab",
"tabs"
],
// ...
}
This solution worked for me in PHP. It opens the PDF in the browser.
// $path is the path to the pdf file
public function showPDF($path) {
if($path) {
header("Content-type: application/pdf");
header("Content-Disposition: inline; filename=filename.pdf");
#readfile($path);
}
}
I've encounterd this problem, and here is my solution for Angular, I wrapped my Angular's asset folder in encodeURIComponent() function. It worked. But still, I'd like to know more about the risk of this solution if there's any:
```const URL = ${encodeURIComponent(/assets/office/file_2.pdf)}
window.open(URL)
I used Angular 9, so this is my url when I clicked open local file:
```http://localhost:4200/%2Fassets%2Foffice%2Ffile_2.pdf```
In the case of audio files, when you give <audio src="C://somePath"/>, this throws an error saying cannot load local resource.
This makes sense because any webpage can't simply give a local path and access your private files.
In case you are trying to play audio with dynamic paths, by changing src property through JS, then here is a sample implementation using Flask server and HTML.
server.py
#app.route("/")
def home():
return render_template('audioMap.html')
#app.route('/<audio_file_name>')
def view_method(audio_file_name):
path_to_audio_file = "C:/Audios/yourFolderPath" + audio_file_name
return send_file(
path_to_audio_file,
mimetype="audio/mp3",
as_attachment=True,
attachment_filename="test.mp3")
audioMap.html
{% raw %}
<!DOCTYPE html>
<html>
<body>
AUDIO: <audio src="Std.mp3" controls >
</body>
</html>
{% endraw %}
Explanation:
When you give the audio file name under src property, this creates a get request in the flask as shown
127.0.0.1 - - [04/May/2021 21:33:12] "GET /Std.mp3 HTTP/1.1" 200 -
As you can see that, the flask has sent a Get request for the Std.mp3 file. So to serve this get request, we wrote an endpoint that takes the audio file name, reads it from the local directory, and returns it back. Hence the audio shows up on UI.
Note: This works only if you are rendering your HTML file using the
render_template method via flask or to say, using flask as your web server.
Google Chrome does not allow to load local resources because of the security .
There is a simple solution for this problem .
1.install live-server plugin in vscode
2.open the html file by live-server
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
How to use webkitRequestFileSystem at file: protocol
jQuery File Upload Plugin: Is possible to preserve the structure of uploaded folders?
How to Write in file (user directory) using JavaScript?
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
I have a problem regarding creating an XML file via a web browser and being able to read/write from it.
Multiple browsers have issues with this and I cant seem to find a solution that works.
I am creating a CMS which displays XML data in fields. I then want to read the values of those input elements and then overwrite the XML file using Javascript or JQuery.
The XML file will be stored on a web server and the client PC's will access the CMS via a webpage on the server and then reading/writing to the XML.
The Code below gives you an idea of what IM trying to do:
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var FILENAME ="xml.xml"; //<---- In Current Directory on Web server.
var file = fso.CreateTextFile(FILENAME, true);
file.WriteLine('<?xml version="1.0" encoding="utf-8"?>\n');
file.WriteLine('<Seating_Plan>\n');
var table = document.getElementById("table_assoc");
var rCount = table.rows.length;
for (var i = 1; i < rCount; i++) {
var id = table.rows[i].cells[0].children[0].value;
var deptcode = table.rows[i].cells[1].children[0].value;
var name = table.rows[i].cells[2].children[0].value;
var role = table.rows[i].cells[3].children[0].value;
var desc = table.rows[i].cells[4].children[0].value;
var image = table.rows[i].cells[5].children[0].value;
var asdir = table.rows[i].cells[6].children[0].value;
file.WriteLine('<Person id="' + id + '"><Dept>' + deptcode + '</Dept><Name>' + name + '</Name><Description>' + desc + '</Description><Role>' + role + '</Role><Image><image href="' + image + '"/></Image><AssociateDir><AssociateDir href="' + asdir + '"/></AssociateDir></Person>');
}
file.WriteLine('</Seating_Plan>');
file.Close();
}
However, This works only when accessing the webpage on a local system rather than the Server eg. via: "file://C:..." rather than:
http://localhost/admin.html
What is the best way to do this?
Any help would be appreciated.
Many thanks!
Aj
I suspect you're misunderstanding something here:
var fso = new ActiveXObject("Scripting.FileSystemObject");
var FILENAME ="xml.xml"; //<---- In Current Directory on Web server.
The web browser can't access the server's file system. That ActiveX object may allow file system access on the current host, but it's not going to allow it on other hosts. If there are no errors and the browser is allowing the ActiveX object to interact with the local file system then I'll bet it's successfully creating the file on the local file system. (In whatever happens to be the current working directory for the browser process, since no directory was specified.)
To interact with files on the server's file system you'll need to use server-side code.
I am building a javascript component for Firefox that will take in a zip code, and will return the current weather conditions.
The sample code that weather underground uses jQuery, but as I understand it, I cannot include this code in my javascript component, as javascript does not have the functionality to include other javascript files.
At any rate, I have built up my skeleton code. It takes in the zip code and builds up the url
(example: http://api.wunderground.com/api/e17115d7e24a448e/geolookup/conditions/q/22203.json)
I have tried downloading the data from that url, via the following method:
getWeatherByUrl: function(url)
{
var persist = Components.classes["#mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Components.interfaces.nsIWebBrowserPersist);
var file = Components.classes["#mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties).get("ProfD",Components.interfaces.nsILocalFile);
file.append("weather-forecaster.dat");
var urlURI = Components.classes["#mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService).newURI(url, null, null);
persist.saveURI(urlURI,null,null,null,"",file);
return url;
}
This should download the file to the user's profile directory. It indeed does create the file there. However, it does not look like it contains the json data from weather underground.
What exactly is going on? How would I download the file? I believe that there is a query going on when that url is passed to weather underground, but that shouldn't matter as the .json page is what gets spit out from them, right?
Is there a way to do this without downloading the file, but by streaming it and parsing it?
You can simply use XMLHttpRequest to download this data:
var request = Components.classes["#mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
request.open("GET", "http://api.wunderground.com/api/Your_Key/geolookup/conditions/q/IA/Cedar_Rapids.json");
request.addEventListener("load", function(event)
{
var data = JSON.parse(request.responseText);
alert(data.response.version);
}, false);
request.send(null);