Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

FAQ Topic - How do I prompt a "Save As" dialog for an accepted mime type? (2010-04-27)

23 views
Skip to first unread message

FAQ server

unread,
Apr 26, 2010, 7:00:02 PM4/26/10
to
-----------------------------------------------------------------------
FAQ Topic - How do I prompt a "Save As" dialog for an
accepted mime type?
-----------------------------------------------------------------------

It is not possible with client-side javascript.

Some browsers accept the Content-Disposition header, but this
must be added by the server. Taking the form:-
` Content-Disposition: attachment; filename=filename.ext `

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

http://support.microsoft.com/kb/q260519/


The complete comp.lang.javascript FAQ is at
http://jibbering.com/faq/

--

The sendings of these daily posts are proficiently hosted
by http://www.pair.com.

Michael Haufe ("TNO")

unread,
Apr 26, 2010, 10:21:45 PM4/26/10
to
On Apr 26, 6:00 pm, "FAQ server" <javascr...@dotinternet.be> wrote:
> -----------------------------------------------------------------------
> FAQ Topic - How do I prompt a "Save As" dialog for an
> accepted mime type?
> -----------------------------------------------------------------------
>
> It is not possible with client-side javascript.
>
> Some browsers accept the Content-Disposition header, but this
> must be added by the server. Taking the form:-
> ` Content-Disposition: attachment; filename=filename.ext `
>
> http://classicasp.aspfaq.com/general/how-do-i-prompt-a-save-as-dialog...

>
> http://support.microsoft.com/kb/q260519/
>
> The complete comp.lang.javascript FAQ is athttp://jibbering.com/faq/
>

I truly wish that this topic was updated from our arguments from last
time...

Michael Haufe ("TNO")

unread,
Apr 26, 2010, 10:22:15 PM4/26/10
to
On Apr 26, 9:21 pm, "Michael Haufe (\"TNO\")"

<t...@thenewobjective.com> wrote:
> I truly wish that this topic was updated from our arguments from last
> time...

s/from/with

Garrett Smith

unread,
Apr 26, 2010, 11:21:05 PM4/26/10
to
Last time it came up, there was no discussion. The time before that, I see:
http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/7414cdc6ca1a0005

- is that what you meant?

Therein, the demo page:
http://thenewobjective.com/temp/save.html

Running that demo in IE7, the image is not displayed. Clicking "prompt
save" results in a javascript error: "The data area passed to a system
call is too small."

I recall another discussion where there was mention of a way to get a
similar effect from IE, however nobody wrote a cross browser solution.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/

Michael Haufe ("TNO")

unread,
Apr 28, 2010, 12:38:11 AM4/28/10
to
On Apr 26, 10:21 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> I recall another discussion where there was mention of a way to get a
> similar effect from IE, however nobody wrote a cross browser solution.
[...]

> I recall another discussion where there was mention of a way to get a
> similar effect from IE, however nobody wrote a cross browser solution.

http://thenewobjective.com/temp/save2.html

This seems to work on all common browsers minus Chrome (where I can't
tell if this is a bug or intentional behavior).

Regardless, the claim that "It is not possible with client-side
javascript." is inaccurate and should be changed to mention the
approaches used through base64 and document.execCommand("SaveAs"...)

The details on what warrants an appropriate example should be separate
debate I think.

Bwig Zomberi

unread,
Apr 28, 2010, 2:10:55 AM4/28/10
to
Michael Haufe ("TNO") wrote:
>
> Regardless, the claim that "It is not possible with client-side
> javascript." is inaccurate and should be changed to mention the
> approaches used through base64 and document.execCommand("SaveAs"...)
>
> The details on what warrants an appropriate example should be separate
> debate I think.

document.execCommand("SaveAs"...) probably works only for the entire web
page, not for a mime type.

--
Bwig Zomberi

Garrett Smith

unread,
Apr 28, 2010, 3:30:34 AM4/28/10
to
Michael Haufe ("TNO") wrote:
> On Apr 26, 10:21 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>> I recall another discussion where there was mention of a way to get a
>> similar effect from IE, however nobody wrote a cross browser solution.
> [...]
>> I recall another discussion where there was mention of a way to get a
>> similar effect from IE, however nobody wrote a cross browser solution.
>
> http://thenewobjective.com/temp/save2.html
>
> This seems to work on all common browsers minus Chrome (where I can't
> tell if this is a bug or intentional behavior).
>

Try putting base64 first in the uri before the content type.
http://en.wikipedia.org/wiki/Data_URI_scheme#Format

Also: "charset ignored in data URIs when data is encoded via base64"
http://code.google.com/p/chromium/issues/detail?id=35582&q=base64%20data&colspec=ID%20Stars%20Pri%20Area%20Feature%20Type%20Status%20Summary%20Modified%20Owner%20Mstone%20OS

> Regardless, the claim that "It is not possible with client-side
> javascript." is inaccurate and should be changed to mention the
> approaches used through base64 and document.execCommand("SaveAs"...)
>
> The details on what warrants an appropriate example should be separate
> debate I think.

The FAQ question "asks how do I..." and so if there is to be an answer
the provides an explanation, it should be a good answer and have a good
example.

The example would have to be a solution where "Save As" dialog is
displayed to save a particular thing that the developer wants.

The butterfly seems to be a more likely case than saving the HTML
document itself. that can be done by setting an iframe source to the
image and then calling:
iframe.contentWindow.document.execCommand("SaveAs");

Needs work.

Ry Nohryb

unread,
Apr 28, 2010, 5:23:07 AM4/28/10
to
On Apr 28, 6:38 am, "Michael Haufe (\"TNO\")"

That's awesome: you set the location.href (.src) on an iframe to be a
data uri with mimetype application/octet-stream so that it gets
downloaded automatically. My browser decodes the base64 encoded
contents and saves it -but without asking anything- as an "unknown"
file of unknown filetype. Well, it's ok, I know it's an html. But for
exactly what type of contents would this trick work well beyond
texts ? If the XHR were for a .png, would it work too ? And is there
anyway to type the downloaded file (add its .png) ? I guess not,
right ? I wonder if not presenting a save as dialog, as in Safari,
could/should be considered a bug. An evil page could do this:

(function loop () {
id("win").src = html64;
setTimeout(loop, 99);
})();

to save files into my HD at a rate of 10 per second (tested in
Safari)... bad.

But the trick is awesome, and it's much better to be told this than to
be told just NO YOU CAN'T NO WAY, as in the FAQ. Good luck with Mr.
Smith the faq guardian, though, as he's quite an asshole. We all
suffer it, and the FAQ suffers it even more.

BTW, the doctype in being written twice into the data uri contents.
--
Jorge.

Bwig Zomberi

unread,
Apr 28, 2010, 7:49:01 AM4/28/10
to
Ry Nohryb wrote:
> On Apr 28, 6:38 am, "Michael Haufe (\"TNO\")"
> <t...@thenewobjective.com> wrote:
>> On Apr 26, 10:21 pm, Garrett Smith<dhtmlkitc...@gmail.com> wrote:
>>
>> The details on what warrants an appropriate example should be separate
>> debate I think.
>
> That's awesome: you set the location.href (.src) on an iframe to be a
> data uri with mimetype application/octet-stream so that it gets
> downloaded automatically. My browser decodes the base64 encoded
> contents and saves it -but without asking anything- as an "unknown"
> file of unknown filetype. Well, it's ok, I know it's an html. But for
> exactly what type of contents would this trick work well beyond
> texts ? If the XHR were for a .png, would it work too ? And is there
> anyway to type the downloaded file (add its .png) ? I guess not,
> right ? I wonder if not presenting a save as dialog, as in Safari,
> could/should be considered a bug. An evil page could do this:

Browser will have to show a dialog box. Otherwise it is a bug. Maybe you
have set Safari not to show any prompts. - "Do not show this prompt
again. Remember this setting."

--
Bwig Zomberi

Ry Nohryb

unread,
Apr 28, 2010, 8:21:07 AM4/28/10
to
On Apr 28, 1:49 pm, Bwig Zomberi <zomberiMAPSONNOS...@gmail.com>
wrote:

>
> Browser will have to show a dialog box. Otherwise it is a bug. Maybe you
> have set Safari not to show any prompts.  - "Do not show this prompt
> again. Remember this setting."

I can't seem to find that preference.. :-( Have you got a Safari to
check it out ? And yes, the dialog pops up in every other browser.

@TNO: For u:

// Modificado por jo...@jorgechamorro.com para detectar webkit's
base64 nativo (atob,btoa)
// Code was written by Tyler Akins and is placed in the public domain
// It would be nice if you left this header. http://rumkin.com


if (!window.btoa) {
window.btoa= function btoa (input) {
var base64_keyStr=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;

do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);

enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;

if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}

output = output + base64_keyStr.charAt(enc1) +
base64_keyStr.charAt(enc2) +
base64_keyStr.charAt(enc3) + base64_keyStr.charAt(enc4);
} while (i < input.length);

return output;
};
}

if (!window.atob) {
window.atob= function atob (input) {
var base64_keyStr=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;

// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

while (i < input.length) {
enc1 = base64_keyStr.indexOf(input.charAt(i++));
enc2 = base64_keyStr.indexOf(input.charAt(i++));
enc3 = base64_keyStr.indexOf(input.charAt(i++));
enc4 = base64_keyStr.indexOf(input.charAt(i++));

chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;

output = output + String.fromCharCode(chr1);

if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}

return output;
};
}
--
Jorge.

Bwig Zomberi

unread,
Apr 29, 2010, 1:15:27 AM4/29/10
to
Ry Nohryb wrote:
> On Apr 28, 1:49 pm, Bwig Zomberi<zomberiMAPSONNOS...@gmail.com>
> wrote:
>>
>> Browser will have to show a dialog box. Otherwise it is a bug. Maybe you
>> have set Safari not to show any prompts. - "Do not show this prompt
>> again. Remember this setting."
>
> I can't seem to find that preference.. :-( Have you got a Safari to
> check it out ? And yes, the dialog pops up in every other browser.
>


Safari does not seem to allow editing of mime-type handling. There is
the option of saving to a folder in Preferences -> General. That's it.

Garrett Smith

unread,
Apr 29, 2010, 1:49:08 AM4/29/10
to

WFM in Safari 4 on Windows. Did not try other versions.

An addendum can be created to explain the technique in further detail,
mention where it works and where it fails, including browser version,
user configuration, etc.

The FAQ entry should be brief and to the point. A new demo page can be
created addressing the idea of not saving the source document itself.
The faq entry and the addendum can link to that demo.

I'll add it to the list of things to do, however if somebody beats me to
it, it would be appreciated.

Garrett Smith

unread,
May 3, 2010, 2:07:26 AM5/3/10
to
As a note to that, saving an image is a more common use case than saving
the file itself.

It is convenient to use this approach for images whose src points to an
actual image binary format, such as png, jpeg, etc. This is especially
common case for high volume sites that use a CDN.

In that case the data is not on the page as a data URI, so we want
something like:

function getDataUrl(img) {
// ...
}

The data URI can be generated by using a canvas element, and calling the
canvas element's `getDataURL` method will return a data URL for the image.

function getImageData(img) {
var cv = document.createElement('canvas'),
ctx = cv.getContext("2d");
ctx.drawImage(img,0,0);
return cv.toDataURL();
}

Unfortunately, this only works if the image was loaded on the same
domain and for a CDN, that is not going to work[1].

Is there another way to get binary data from an image?
[1]<http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#security-with-canvas-elements>

Ry Nohryb

unread,
May 3, 2010, 8:02:17 AM5/3/10
to
On May 3, 8:07 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>
> As a note to that, saving an image is a more common use case than saving
> the file itself.
>
> It is convenient to use this approach for images whose src points to an
> actual image binary format, such as png, jpeg, etc. (...)

Yeah, Smith, but it's not going to work. You can't get straight binary
data because the encoding of responseText defaults to UTF-8, and in
UTF-8 any char > 0x7f and <= 0xff is converted to utf 0xfffd -->
broken image. Maybe, just may be, you could fix that by specifying a
more appropriate charset in the content-type header of the response
(something that in general is *never* specified for images), but then
you'd have to split any chars >0x00ff into two separate chars in order
to be able to feed it to the btoa().
--
Jorge.

Ry Nohryb

unread,
May 3, 2010, 8:15:48 AM5/3/10
to

Some tools to see it by yourself:

function fetch (url) {
var xhr= new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.send(null);
document.body.innerHTML= "<p>"+ hexdump(xhr.responseText)+ "</p>";
}

function hexdump (input, r, i) {
r= "";
if (typeof input === "string") {
i= 0;
while (i < input.length) {
r+= hexdump(input.charCodeAt(i++));
}
} else if (typeof input === "number") {
i= input.toString(16);
i= (i.length < 2) ? "0"+i : i;
r= i+ ".";
}
return r;
}

Instructions:

1.- paste and compile it in the console.
2.- fetch("urlOfAnImage")
3.- see how many .fffd(s) you get: each one is a broken byte.
--
Jorge.

0 new messages