Detecting iframe load when downloading a file through the iframe - javascript

I'm using AngularJS and setting ngSrc on an iframe, which I use to download a zipped archive to get around not being able to download files using AJAX. I'm using a directive for detecting the iframe load that I found here, which works great when you load a URL like "about:blank", but it doesn't have a load when I hit it with a RESTful call to download the file, even though it downloads the generated file.
// Markup of iframe using ngSrc and custom directive
<iframe ng-src="{{url}}" style="display:none;" iframe-onload="myCallback" />
// Controller setting iFrame, what I'd like to trigger the load
$scope.downloadArchive = function( id ) { // no load event? but downloads zip archive
var url = '/data/archive/instance/' + id;
$scope.url = $sce.trustAsResourceUrl( url );
}
// Controller setting iFrame, what does trigger the load
$scope.downloadArchive = function( id ) { // load event triggered
$scope.url = $sce.trustAsResourceUrl('about:blank');
}
Is is possible to detect an event when downloading a zipped archive through the iframe?

Is it that you can't download the file via AJAX due to browser restrictions? Like cross domain issues? You can find out by examining the error in Chrome Console.
If that is the case, you won't be able to view the contents of the file in an iframe either due to modern browser restrictions. Think of what can happen if developers are allowed to access the contents of any iframe. I could make a website with your bank's website in an iframe. Once you log in, I'd be able to listen to a form submit event from the iframe and then get your login credentials.
Hence, what could be happening is that your iframe is loading the file, trying to display the file within it, but intentionally hindering you from viewing its contents for security.
I'd recommend downloading the file via a proxy server you own or through a cloud service, and then serving the file from your own server. This circumvents cross domain issues since you can now ping your own server.

I ended up not trying to reset the URL each time and just appended the current time as a second parameter, which gets ignored by the server. Now it appears like iframe is reloading a new URL.
var url = '/data/archive/instance/' + id + '/' + Date.now();

Related

Dynamic fetch for static HTML page without webserver

There's a static page myapp/page.html and a static file in same directory myapp/data.txt. I would like to open that page in Browser from the file system, without web server, and get content of the myapp/data.txt file. It should be possible periodically reload that file to check if its content changed.
fetch('file:///myapp/data.txt') is not working because of some security error Fetch API cannot load file:///myapp/data.txt
Loading as an image img.src='data.txt' also not working, it loads the file it could be seen in the networking tab, but when you try to read it as the image content it tells that image is broken.
As a last resort it's possible to change data.txt into data.js and load it via script.src='data.js' but maybe it's somehow possible to load it as a text too?
As a last resort it's possible to change data.txt into data.js and load it via script.src='data.js' but maybe it's somehow possible to load it as a text too?
Yeah, you could use the old JSON-P method, but with a statically-named function.
Basically, you have in your main script something like this:
window.onDataLoad = (data) => {
// do something with data here
}
// Inject script tag wherever you want to reload the data
const scriptEl = document.createElement('script');
scriptEl.src = 'data.js';
document.querySelector('head').appendChild(scriptEl);
Then, in your data.js, something like:
window.onDataLoad( << YOUR DATA HERE >> );
Finally... just wanted to note that I sympathize! It's ridiculous that fetch() can't handle this. What a great opportunity to abstract the fetching of data from HTTP, when moving away from XHR. Sadly, this didn't happen.

JavaScript: Read URL of parent page

I have a page that is loaded inside. The application including this page is located on another domain. So the domain of my page and the application rendering it inside an iframe are located on different domains. The page inside iframe reads the URL it is loaded from to store in the database. The page loading has a hash in the URL.It is like:
https://www.somedomain.com/organizers/list/#type=current&sort=bydate
I am reading the URL from mypage. It is located on:
https://www.someotherdomain.com/organizers/#sample
var _url = document.referrer
The above code gives me the URL but only till "https://www.somedomain.com/organizers/list/", "#type=current&sort=bydate" is missing. I need that else this code is of no use to me. Is there a way I can read the complete URL without missing any segment?
like this
var _url = window.location;
This is by design. The browser will give you the referrer which is the URL where the user came from, however the #hashmark is technically (by its original design) a sub-navigation concept within a page, thus not passed on to the next page load.
If you were on the same domain as the parent page, you could access it via the
window.parent.location.hash
however since you are from a different domain this access will likely be blocked for security reasons.

refresh iframe after downloading a blob

I have a filebrowser on my server that uses Azure storage to store the files. The website has a feature where when you click on a file, it'll bring up a details window. I use ViewerJS to display a pdf preview of the file (if applicable), and it all works pretty well. The only problem is that when downloading the preview file, you have to reload the preview iframe manually to get it to display. The relevant php function is:
http://pastebin.com/sAyhsbfi
When this function is completed (I'm using ajax), the $.done function calls
response = JSON && JSON.parse(response) || jQuery.parseJSON(response);
$scope.pdfthingy=response; document.getElementById("viewerjs_preview").contentDocument.location.reload(true);
where response on the first line is set to the full pathname to the pdf preview file, and viewerjs_preview is the id of the relevant iframe.
For some reason, this isn't working, and the iframe isn't reloading itself. How do I make it do that when the blob has finished downloading, and pdfthingy is set?
Is the iframe’s domain the same as your host website’s domain? If not, we cannot access its contentDocument (or contentWindow) in host website’s JavaScript code.
To refresh the iframe, per my understanding you can set its src:
document.getElementById('viewerjs_preview').src = document.getElementById('viewerjs_preview').src;
Please note if the src contains a hash tag, we may need additional work. I’d like to suggest you to check What's the best way to reload / refresh an iframe using JavaScript? for more information.
Base on my experience, It is possible that we changed the IFrame URL, but the IFrame showed the preview contents. In this scenario, I suggest you can create the IFarme dynamic. For example, When you got the Blob URI form Azure storage, You could try to remove the Iframe and create a new. For instance, if Your preview content is shown in the iframe as :
<iframe id="viewerjs_preview" src = "/ViewerJS/#../azure blob storage url /pre-blobname .pdf " width='400' height='300' allowfullscreen webkitallowfullscreen></iframe>
You can try to use this code:
function recreateIFM() {
document.getElementById("viewerjs_preview").parentNode.removeChild(document.getElementById("viewerjs_preview"));
var ifm = document.createElement("iframe");
ifm.id = "viewerjs_preview";
ifm.width = "600px";
ifm.height = "400px";
ifm.src = "/ViewerJS/#../azure blob storage url /new-blobname .pdf";
document.body.appendChild(ifm);
}
Also, you can try MingXu's reference about how to refresh/reload the Iframe.
Regards,
Bill_Sww
I find the answer, the major reason is that we shouldn't use controllers to manipulate DOM.
sentence like document.getElementById("viewerjs_preview").contentDocument.location.reload(true) will not work anymore in angular scope, so you have to a directive to do it. I think the same question with you is and which's answer with most votes dose work well.
I think maybe my question was unclear, and for that I apologize. I'll try to go back and edit it tomorrow.
The solution for me was to, rather than set the src attribute of the iframe using angularjs, directly set it with
document.getElementById("iframe-id").src=/path_where_I_put_the_files/filename
(for reference I use "pdfthingy" to store the filename returned by the ajax call that downloads a blob).
This prevented the iframe from loading a null source before the filename was set.
This is perhaps part of why walkformusle has said that DOM should not be controlled in this manner.

Start file download by client from Javascript call in C#/ASP.NET page?

I need to initiate file download from ASP.NET page from javascript code.
What would be my best option? Is it possible to call a webservice to do so, or somehow call usual event handler of C# page?
Note that I will retrieve a large amount of data, many megabytes.
You can use a hidden IFRAME element and initiate a file download request, which does give the feeling for a AJAX file download.
While the file is being downloaded you can do other activity in your form on client side.
Yes you can call a webservice or aspx page or http handler as well in this URL
function dowloadFileJS() {
// Create an IFRAME.
var iframe = document.createElement("iframe");
// Point the IFRAME to GenerateFile
iframe.src = "GenerateFile.aspx?yourQueryString=myQueryString";
// This makes the IFRAME invisible to the user.
iframe.style.display = "none";
// Add the IFRAME to the page. This will trigger a request to GenerateFile now.
document.body.appendChild(iframe);
}
You can use Javascript to create an iframe to the file you want to download. Have a look at this answer: Starting file download with JavaScript

Follow a URL using JavaScript

Is there any way to follow a URL in JavaScript without setting the document.location.href?
I have a page that displays a list of objects and each object may have a file download associated with it, which is accessed via a hyperlink. Clicking the link initiates an AJAX request that ultimately leads to a transient file being generated that can be referenced by a unique and temporary URL.
At the moment when the AJAX call completes, it simply sets the document.location.href to the temporary URL and the file download is initiated. Of course this has the side effect of changing the URL in the browser's address bar, so if the page is refreshed the file is downloaded again rather than the object listing page itself getting refreshed. I guess I could set the URL back to what it was before, but that feels a bit hacky.
Incidentally, I'm using the Prototype JavaScript framework.
you could open a new window with the new url? or try setting an iframe's url to the new url, both should present a file download (the latter being the better option)
You could use a hidden iframe - set the src of that to the file to download.
If you're doing all this just to trigger a file download, it sounds like a good application for using a hidden Iframe. Set the SRC of the Iframe instead, so you don't have to mess with the main page.

Categories