Possible to generate text files in javascript?

56 views
Skip to first unread message

kerinin

unread,
Dec 12, 2007, 7:37:28 PM12/12/07
to
I'd like to be able to generate a text file in a web browser, then
supply a link which will allow users to save that file to disk. I'm
not trying to read from the local machine or even write directly to
the local machine, I'm simply trying to provide a file which the local
browser and save as it would any other URL.

Just to give some idea of my motivation, I'm working with encrypted
data which is decrypted locally (so the server never has access to the
data). I'd like to be able to save the cleartext in some cases as a
text file.

Thanks
-Ryan

Randy Webb

unread,
Dec 12, 2007, 9:22:33 PM12/12/07
to
kerinin said the following on 12/12/2007 7:37 PM:

User clicks a button.
Browser opens new window with text file.
User uses File>Save As to save the text file.

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq/index.html
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

kerinin

unread,
Dec 12, 2007, 9:40:55 PM12/12/07
to
> User clicks a button.
> Browser opens new window with text file.
> User uses File>Save As to save the text file.
>
> --
> Randy
> Chance Favors The Prepared Mind
> comp.lang.javascript FAQ -http://jibbering.com/faq/index.html
> Javascript Best Practices -http://www.JavascriptToolbox.com/bestpractices/

Wouldn't the new window have HTML formatting as well as the text?

Peter Michaux

unread,
Dec 12, 2007, 11:46:04 PM12/12/07
to
On Dec 12, 6:40 pm, kerinin <keri...@gmail.com> wrote:
> > User clicks a button.
> > Browser opens new window with text file.
> > User uses File>Save As to save the text file.
>

[snip]

>
> Wouldn't the new window have HTML formatting as well as the text?

If the servers sends the file with a "Content-Type text/plain" header
then it will just show as text.

Peter

kerinin

unread,
Dec 13, 2007, 9:30:42 AM12/13/07
to
> If the servers sends the file with a "Content-Type text/plain" header
> then it will just show as text.
>
> Peter

The problem is that I don't want the server to have access to the data
- could the server send a blank document and then the client machine
could modify the text in it, or can the document.write functions only
operate on html Content-Types? Or alternately, could I open a new
window with javascript and specify a blank URL with content type text/
plain?

Thanks again
-Ryan

Thomas 'PointedEars' Lahn

unread,
Dec 13, 2007, 1:38:55 PM12/13/07
to
kerinin wrote:
> I'd like to be able to generate a text file in a web browser, then
> supply a link which will allow users to save that file to disk. I'm
> not trying to read from the local machine or even write directly to
> the local machine, I'm simply trying to provide a file which the local
> browser and save as it would any other URL.

MSHTML-based user agents at least since version 4.0 (e.g. IE 4.0+ for
Windows) and Gecko-based UAs since version 1.8 (e.g. Firefox 1.5+) [1] support

document.open("text/plain");
document.write("foo\nbar");
document.close();

where `document' is a reference to an object that implements `document' from
DOM Level 0 [2] and/or HTMLDocument from DOM Level 2 HTML [3] (but with this
proprietary extension). Meaning that it may also be

var w = window.open("", "...", "...");
w.document.open("text/plain");
...

The possible "link" would have to trigger another proprietary feature of the
UA's AOM. MSHTML at least since version 5.01 supports

document.execCommand("SaveAs", false, "C:\\foo\\bar.txt");

where the same conditions as described above apply. This opens a dialog
window that proposes to save the resource as C:\foo\bar.txt [4]

Passing `true' to prevent the "Save As" dialog from opening had no effect.
Probably that is because users would frown upon Web authors saving files to
their storage medium, other than cookies, without their explicit consent.
Omitting the target filename or suffix proposed to save the document as
(invalid) HTML with an .html suffix and the content wrapped in a `pre' element.


PointedEars
___________
[1] http://www.mozilla.org/projects/deerpark/new-web-dev-features.html
[2] http://docs.sun.com/source/816-6408-10/document.htm
http://developer.mozilla.org/en/docs/DOM:document
http://msdn2.microsoft.com/en-us/library/ms535862.aspx
[3] http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268
[4] http://msdn2.microsoft.com/en-us/library/ms536419.aspx pp.
http://msdn2.microsoft.com/en-us/library/ms537418.aspx
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee

Peter Michaux

unread,
Dec 13, 2007, 10:48:39 PM12/13/07
to

Seems like an odd thing to be doing.

I don't think there is any way to specify content type with
window.open().

You could dump the text in a textarea and tell the user to copy and
paste it.

Using a little flash movie you can put the content into the users
system clipboard and the user could paste it into a file. This
clobbers what is already in their clipboards so give them a warning.

Peter

Peter Michaux

unread,
Dec 13, 2007, 10:50:23 PM12/13/07
to
On Dec 13, 7:48 pm, Peter Michaux <petermich...@gmail.com> wrote:
> On Dec 13, 6:30 am, kerinin <keri...@gmail.com> wrote:
>
> > > If the servers sends the file with a "Content-Type text/plain" header
> > > then it will just show as text.
>
> > > Peter
>
> > The problem is that I don't want the server to have access to the data
> > - could the server send a blank document and then the client machine
> > could modify the text in it, or can the document.write functions only
> > operate on html Content-Types? Or alternately, could I open a new
> > window with javascript and specify a blank URL with content type text/
> > plain?
>
> Seems like an odd thing to be doing.
>
> I don't think there is any way to specify content type with
> window.open().

I meant to write "no cross-browser way".

VK

unread,
Dec 14, 2007, 9:09:56 AM12/14/07
to
On Dec 13, 5:30 pm, kerinin <keri...@gmail.com> wrote:
> > If the servers sends the file with a "Content-Type text/plain" header
> > then it will just show as text.

It is not exactly true. Any browser is an application to display HTML
documents. Any other type of document - including text/plain -
requires a separate plugin so to be displayed as separate object
withing HTML page. An exception is made for text/plain as a very
common type displayed in browsers. Instead of plugin, browser at
runtime generates a minimum HTML page
<HTML><BODY><PRE>text/plain content</PRE></BODY></HTML>
and displays it. This mechanics goes on the background, so if you say
saving a page, it will be again some.txt Unfortunately this mechanics
is not fully hidden on Gecko so say documentElement.firstChild returns
HEAD element for text/plain which may be very confusing if not knowing
the background mechanics.

Back to the OP question and as already pointed by Thomas, there is a
convenient solution for IE, much lesser convenient for Gecko - and
maybe newer Gecko has something better to propose and maybe IE7 has
more strict security for execCommand, needs to be checked. I am
talking only about solutions within the default security restrictions.

For IE one can use document.execCommand with SaveAs argument.
For Gecko one can use bug # 367231
https://bugzilla.mozilla.org/show_bug.cgi?id=367231
as it was explained to me by developers it is not a bug but a feature
so to remain in future releases.

So it maybe something like (test.txt file has to be in the same
directory where the page is in order to see the script in action):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Save As</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function saveAs(doc) {
if (typeof document.execCommand == 'object') {
doc.execCommand('SaveAs', false, 'C:\\foobar.txt');
}
else if (
(navigator.userAgent.indexOf('Gecko')!=-1) &&
(netscape) &&
(netscape.security)) {
var txt = doc.getElementsByTagName('PRE')[0].firstChild.nodeValue;
window.location = 'data:plain/text,' + escape(txt);
}
else {
}
}

function init() {
window.frames['UIN'].document.designMode = 'on';
}
window.onload = init;
</script>
</head>

<body>
<form method="post" action="">
<fieldset>
<legend>Save As</legend>
<iframe name="UIN" src="test.txt"
style="
width: 20em;
height: 3em;
display: -moz-inline-box;
display: inline-block;"></iframe>
<br>
<input type="button" value="Save As"
onclick="saveAs(window.frames['UIN'].document)">
</fieldset>
</form>

<noscript>
<p style="color:red">If you see this text then it means
that the current browser settings do not allow script
execution for this page.</p>
</noscript>
</body>
</html>

VK

unread,
Dec 14, 2007, 12:32:18 PM12/14/07
to
> Possible to generate text files in javascript?

<g>
It look like I have got a pair of k of bucks from the sky blue as a
solution like that for the default security was deadly needed for a
guy I know. JavaScript pays my Tahoe trip, who could think... :-)

An updated solution - if anyone else needs it - could be like:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>


<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">

<title>Save As</title>
<script type="text/javascript">
/* (c) 2007 VK [school...@yahoo.com]
* All copyrights are given to the world.
*/
function saveAs(doc, path) {
if (('ActiveXObject' in window) &&
(typeof document.execCommand == 'object')) {
try {
doc.execCommand('SaveAs', false, path);
}
catch(e) {
window.alert('Save As error:\n'+
(e.number & 0xFFFF)+' '+e.message);
}
}
else if (('GeckoActiveXObject' in window) &&


(netscape) && (netscape.security)) {
var txt = doc.getElementsByTagName('PRE')[0].
firstChild.nodeValue;

window.location = saveAs.GeckoPrompt + escape(txt);
}
else {
window.alert('Required feature is missing');
}
}
saveAs.GeckoPrompt = 'data:TEXT FILE Please add .txt extension,';

function init() {
window.frames['UIN'].document.designMode = 'on';
}
window.onload = init;
</script>
</head>

<body>
<form action="" onsubmit="return false;">


<fieldset>
<legend>Save As</legend>

<p><iframe name="UIN" src="test.txt"
style="width:30em; height:3em;"></iframe></p>
<p><button type="button" accesskey="s"
onclick="
saveAs(window.frames['UIN'].document, 'C:\\foobar.txt')">
<u>S</u>ave</button></p>

VK

unread,
Dec 14, 2007, 2:53:51 PM12/14/07
to
On Dec 13, 9:38 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> MSHTML-based user agents at least since version 4.0 (e.g. IE 4.0+ for
> Windows) and Gecko-based UAs since version 1.8 (e.g. Firefox 1.5+) [1] support
>
> document.open("text/plain");
> document.write("foo\nbar");
> document.close();

Yeah, I forgot to mention: that is your fantasy, IE never supported
anything but "text/html" for MIME in document.open method. Actually
MSDN is very explicit about it as well:

http://msdn2.microsoft.com/en-us/library/ms536652.aspx
"text/html Default. Currently the only MIME type supported for this
method."

By using document.open('text/plain') one trigs "unsupported MIME type
argument protection" in IE with some very funny consequences. Try this
old demo for instance (try to File/Save as/ from the new window with
the "text file"):

<html>
<head>
<title>Untitled Document</title>


<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">

</head>
<body>
<script>
var w = window.open('about:blank');
window.setTimeout('f()',1000);
function f() {
w.document.clear();
w.document.open('text/plain');
w.document.write('Text');
w.document.close();
}
</script>
</body>
</html>

Thomas 'PointedEars' Lahn

unread,
Dec 14, 2007, 4:10:47 PM12/14/07
to
VK wrote:
> On Dec 13, 9:38 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
> wrote:
>> MSHTML-based user agents at least since version 4.0 (e.g. IE 4.0+ for
>> Windows) and Gecko-based UAs since version 1.8 (e.g. Firefox 1.5+) [1] support
>>
>> document.open("text/plain");
>> document.write("foo\nbar");
>> document.close();
>
> Yeah, I forgot to mention: that is your fantasy, IE never supported
> anything but "text/html" for MIME in document.open method.

You are confusing things, the expert on publishing fantasies is *you*.
I have of course *tested* the above statement positive in the following UAs:

Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 5.0;
{3E1C4754-F096-BBFE-CD76-3B2E8F19E202})

Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0;
{3E1C4754-F096-BBFE-CD76-3B2E8F19E202}; .NET CLR 2.0.50727)

Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.1;
{3E1C4754-F096-BBFE-CD76-3B2E8F19E202}; .NET CLR 2.0.50727)

Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;
{3E1C4754-F096-BBFE-CD76-3B2E8F19E202}; .NET CLR 2.0.50727)

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1;
{3E1C4754-F096-BBFE-CD76-3B2E8F19E202}; .NET CLR 2.0.50727)

Except of IE 7, these are the standalone versions of course, however I have
also tested other DOM features with these and observed the expected result;
e.g. document.getElementById() was not supported in Standalone IE 4.01 but
since 5.01.

> Actually MSDN is very explicit about it as well:
>
> http://msdn2.microsoft.com/en-us/library/ms536652.aspx
> "text/html Default. Currently the only MIME type supported for this
> method."

The MSDN Library is incorrect then.

> By using document.open('text/plain') one trigs "unsupported MIME type
> argument protection" in IE with some very funny consequences.

Utter nonsense.


PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>

VK

unread,
Dec 14, 2007, 4:30:41 PM12/14/07
to
On Dec 15, 12:10 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>

wrote:
> VK wrote:
> > On Dec 13, 9:38 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
> > wrote:
> >> MSHTML-based user agents at least since version 4.0 (e.g. IE 4.0+ for
> >> Windows) and Gecko-based UAs since version 1.8 (e.g. Firefox 1.5+) [1] support
>
> >> document.open("text/plain");
> >> document.write("foo\nbar");
> >> document.close();
>
> > Yeah, I forgot to mention: that is your fantasy, IE never supported
> > anything but "text/html" for MIME in document.open method.
>
> You are confusing things, the expert on publishing fantasies is *you*.
> I have of course *tested* the above statement positive

You may rethink your idea of "positive test" a.s.a.p. then.

<html>
<head>
<title>Demo</title>


<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
</head>
<body>
<script>
var w = window.open('about:blank');

/* timeout is only to avoid
* ideas of page not ready yet
* and similar
*/


window.setTimeout('f()',1000);
function f() {
w.document.clear();
w.document.open('text/plain');

w.document.write('foo\nbar');
w.document.close();
}
</script>
</body>
</html>

1) Open the page in IE 6.
2) In the popup window wait a sec until "foo bar" text appears.
3) In the popup window choose File / Save As... /
4) Default file type is HTML, not TEXT
5-a) Click OK and observe that the saved page is not from pupup, but
the stating one with the script - but converted to Unicode with BOM in
front of the first tag. No foo, no bar.
5-b) Manually change to Text File and save. OK, kind of working but
still in Unicode (line breaks mistreated if no Unicode support in the
text viewer).
5-c) Instead of "about:blank" use an initial text file. Observe no
difference in the behavior.
6) Enjoy.

Thomas 'PointedEars' Lahn

unread,
Dec 14, 2007, 6:20:53 PM12/14/07
to
VK wrote:
> [...] Thomas 'PointedEars' Lahn [...] wrote:
>> VK wrote:

>>> [...] Thomas 'PointedEars' Lahn [...] wrote:
>>>> MSHTML-based user agents at least since version 4.0 (e.g. IE 4.0+ for
>>>> Windows) and Gecko-based UAs since version 1.8 (e.g. Firefox 1.5+) [1] support
>>>> document.open("text/plain");
>>>> document.write("foo\nbar");
>>>> document.close();
>>> Yeah, I forgot to mention: that is your fantasy, IE never supported
>>> anything but "text/html" for MIME in document.open method.
>> You are confusing things, the expert on publishing fantasies is *you*.
>> I have of course *tested* the above statement positive
>
> You may rethink your idea of "positive test" a.s.a.p. then.

With your providing an inappropriate (and syntactically invalid) test case?
Certainly not.

> var w = window.open('about:blank');

Why do you introduce `about:blank', another, possibly incompatible,
pseudo-protocol?

> /* timeout is only to avoid
> * ideas of page not ready yet
> * and similar
> */
> window.setTimeout('f()',1000);
> function f() {
> w.document.clear();

Why do you introduce another now-proprietary[1] feature? And why do you
call the method *before* opening the output stream -- a method about which
the MSDN Library states:

| clear Method
|
| Not currently supported. To clear all elements in the current document,
| use document.write(""), followed by document.close."
|
| Standards Information
|
| This method is defined in World Wide Web Consortium (W3C) Document
| Object Model (DOM) Level 1 World Wide Web [DOM].

?

[1] <http://www.w3.org/TR/DOM-Level-2-HTML/>
"Status of this Document" --> "Note"

> w.document.open('text/plain');
> w.document.write('foo\nbar');
> w.document.close();
> }
> </script>
> </body>
> </html>
>
> 1) Open the page in IE 6.
> 2) In the popup window wait a sec until "foo bar" text appears.
> 3) In the popup window choose File / Save As... /
> 4) Default file type is HTML, not TEXT

Apparently you have not been paying attention. I have said that with

document.execCommand("SaveAs", ...)

the filename suffix is .html and file content is HTML but if you provide
`.txt' as suffix it is actually saved as plain text by default. Of course
that behavior is the same with the menu item that triggers this
functionality if the same "File type" option is selected.

> 5-a) Click OK and observe that the saved page is not from pupup, but
> the stating one with the script - but converted to Unicode with BOM in
> front of the first tag. No foo, no bar.

That is true, but ...

Evidently now, you have not been paying attention. I have used
document.execCommand() to trigger the "Save As" operation, not
the menu option (in fact, my popup does not even need a menu bar).

I recognize that there is a bug with the "Save As" menu item and the "Web
page, complete (*.htm;*.html)" and "Web page, single file (*.mht)" "File
type" option in IE, however that is irrelevant here as I did not propose to
use either one. (Besides, the OP wanted the user to save something as text,
so even if they do not implement the document.execCommand() suggestion, it
is unlikely that the user will leave the "File type" option at "HTML"; so it
is unlikely that the bug occurs.)

A (proper) test case can now be found at
http://PointedEars.de/scripts/test/dom/text-save

> 5-b) Manually change to Text File and save. OK, kind of working but
> still in Unicode (line breaks mistreated if no Unicode support in the
> text viewer).

Nothing is wrong with saving as "Unicode" text (which is then actually
UTF-16LE-encoded text without BOM). Even, and especially, the Windows
Notepad (at least since Windows 2000) can display that properly. (In fact,
ECMAScript 3 implementations use that encoding internally for parsing code
and storing string values.)

> 5-c) Instead of "about:blank" use an initial text file. Observe no
> difference in the behavior.
> 6) Enjoy.

ISTM you enjoy to boldly present your misconceptions where no one presented
them before[tm], and be corrected each and every single time.


PointedEars
___________
[tm] I am allowed to make that kind of pun ;-)

Reply all
Reply to author
Forward
0 new messages