views:

3061

answers:

3

I need a cross-browser solution to the following use case: The user clicks an "export" button on one of our pages, which opens a popup with a form. On submitting the form, the user should receive a binary file download (a CSV file, for example), and the popup should close without changing the visible content of the parent window.

We can't use a timeout to close the popup, because there's typically a dialog asking the user how to handle the file before downloading it, and there's no way of knowing how long it will take the user to handle this dialog.

We originally had a script in the popup which sets window.location to the download file URL. That leaves the popup unclosed.

So then I tried putting a hidden iFrame in the parent window and having the popup set the iFrame's src to the download URL before calling self.close(). That works perfectly in Firefox, but IE completely mangles it with security restrictions.

Is there a right way to do this ? How about a way that works on IE ?


Update - problem solved

The answers proposed here were not too far off, but my problem was a bit more complex than just being a Javascript issue. I encountered bugs with IE and Excel (since the download file is CSV), and the popup was doing a form post.

I could not solve the problem without appending the form data to a URL (for a GET instead of a POST), and I have to set the site as trusted in IE (this is an enterprise app, so that's a reasonable request to make of the users).

On the click of the form button, the popup calls a function on window.opener, passing in the form and its action URL. Then the popup calls window.close(). The function appends the form data to the URL and sets window.location to the new URL (the iFrame idea never worked well in IE and apparently was not necessary).

In the response to the form URL, the request headers include Content-Type: application/octetstream and Content-Disposition", "attachment; filename=filename.csv".

A: 

This might be the a way to approach the problem.

1) Popup form onsubmit does a window.open to a third window that opens a page that is a blank page that just returns the downloaded file.

2) In your javascript on the popup form, right after you do the window.open, call your parent window (the 1st window) method that closes the popup submit form.

3) On the third page, which is just the page that returns the file, you the content-disposition in your header file to just return the file and nothing else, so the page won't really open.

Here is some info on the header you might need. The code is in Classic prehistoric ASP, but you should be able to gleam what you need.

http://classicasp.aspfaq.com/general/how-do-i-prompt-a-save-as-dialog-for-an-accepted-mime-type.html

Hope that helps.

infocyde
I'm not sure step 1 would work in my case, because the form submission in the popup actually generates the file to be downloaded and names it. Until I get the results of this submission, I can't open the third window because I don't know the download URL. That's a solvable problem, but I was hoping not to have to touch the file download servlet itself, since this is a bug fix late in our development cycle.
+1  A: 

Have you tried, in the iframe solution, to actually call a method inside the parent window, which in turn will set the location of the iframe? I'm asking because it worked in my tests:

Parent Window

<html>
<head>
<script type="text/javascript">
var w;

var download = function() {
    document.frames[0].location = "test.php";
    w.close();
};

var o = function() {
    w = window.open("test2.html", "window_name");
    return false;
};
</script>
</head>
<body>

<a href="#" onclick="return o();">open</a>

<iframe></iframe>

</body>
</html>

Popup window

<html>
<head>
<script type="text/javascript">
var download = function() {
    window.opener.download();
    return false;
};
</script>
</head>
<body>

<a href="#" onclick="return download();">download</a>

</body>
</html>

test.php is just a page that forces a file for download, and please note that the above code is IE specific as I'm using the document.frames object, but it can be easily made cross-browser.

Ionuț G. Stan
At the time of the generation of the parent page, the file download URL is not known. I suppose it could be passed in to the download() function. I'll have to try this (early next week, due to my schedule).
Putting the download() function in the opener did not fix things. IE still blocks and completely mangles the download process. Next step for me is to try loading the form in the iFrame rather than in the popup.
What version of IE?
Ionuț G. Stan
I have IE 6.0. We're supposed to support IE7, too.
A: 

There is not any perfect solution for it . When file download in IE its popup and in firefox it directely downloaded