206

I have a text file in the root of my web app http://localhost/foo.txt and I'd like to load it into a variable in javascript.. in groovy I would do this:

def fileContents = 'http://localhost/foo.txt'.toURL().text;
println fileContents;

How can I get a similar result in javascript?

danb
  • 10,239
  • 14
  • 60
  • 76

9 Answers9

165

XMLHttpRequest, i.e. AJAX, without the XML.

The precise manner you do this is dependent on what JavaScript framework you're using, but if we disregard interoperability issues, your code will look something like:

var client = new XMLHttpRequest();
client.open('GET', '/foo.txt');
client.onreadystatechange = function() {
  alert(client.responseText);
}
client.send();

Normally speaking, though, XMLHttpRequest isn't available on all platforms, so some fudgery is done. Once again, your best bet is to use an AJAX framework like jQuery.

One extra consideration: this will only work as long as foo.txt is on the same domain. If it's on a different domain, same-origin security policies will prevent you from reading the result.

Pharoah Jardin
  • 134
  • 2
  • 9
Edward Z. Yang
  • 26,325
  • 16
  • 80
  • 110
  • 1
    A workaround for the same-origin policy is using [JSONP](http://en.wikipedia.org/wiki/JSONP) that also is supported by jQuery (for the client side part) – OneWorld Jul 29 '12 at 17:19
  • 6
    it might be usefull to add that, inside onreadystatechange, you can access the readystate property of the XMLHttpRequest Object (in the example : client.readystate ) to know what is the status, since the onreadystatechange event is raised for loading, loaded, .... so you must wait for client.readystate == 4 inside onreadystatechange before you can use client.responseText. – GameAlchemist Oct 19 '12 at 21:52
  • 3
    @GameAlchemist: stumbled upon your great answer. I just wanted to note that in most browsers readyState is camel cased, so the code should be something like this: ```if (client.readyState === 4){ }``` – snorpey Nov 23 '13 at 16:55
  • 9
    Additionally you can do `client.onloadend` and just get the completed data – worbel Jun 30 '14 at 04:53
  • 3
    The answer should be redacted to include checking for the `client.readyState` property value. I am downvoting it until it is, people are not going to read the comments to discover the answer is only partially right. – Armen Michaeli Feb 01 '15 at 20:51
  • 1
    I get the error `Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.` – pixelpax Sep 16 '15 at 16:44
  • There are plenty of solutions out there. This one is just great. – Evhz Jul 07 '16 at 19:09
  • @OneWorld JSONP can only be used to load JSON data, can't it? I thought it couldn't be used to load text (`foo.txt`) which is what the OP wants, nor to load e.g. XML. – ChrisW Aug 28 '16 at 10:32
  • If the text your trying to load happens to be just some config required for your javascript to run... consider reformatting your config into a little javascript file that sets a javascript variable and use to load it. – andrew pate Aug 30 '20 at 12:30
89

here is how I did it in jquery:

jQuery.get('http://localhost/foo.txt', function(data) {
    alert(data);
});
danb
  • 10,239
  • 14
  • 60
  • 76
  • that doesn't seem to work with plain tabular text data (http://docs.jquery.com/Specifying_the_Data_Type_for_AJAX_Requests) – pufferfish Jan 09 '12 at 14:49
  • 9
    Notice that this does not work if you're testing it locally using `file://` i.e.: `file:///example.com/foo.html`. Firefox complains of a syntax error and Chrome blocks because it considers it as a Cross-Origin request. – Akronix Aug 28 '15 at 17:26
  • @pufferfish it'll work with plain data if you specify the `dataType` parameter, see [api.jquery.com/jQuery.get/](http://api.jquery.com/jQuery.get/) – yvesonline Dec 27 '15 at 03:06
  • 3
    @Akronix if you leave out the `http://...` part, because it lives on the same domain, it'll work, e.g. `jQuery.get("foo.txt", ...)`. – yvesonline Dec 27 '15 at 03:09
  • @Akronix Is there an easy way to test it locally? I keep getting Cross-origin request errors – ahuff44 Feb 05 '16 at 22:54
  • This works for me, when I added localhost:9090 (the port address my server is using). – Yan King Yin May 02 '16 at 11:07
  • @yvesonline Ok `jQuery.get("foo.txt", ...)` solves the Cross-Origin problem, but another comes: `not well-formed` error, and it's impossible to load the content. I don't see why this doesn't work and why [this works](http://stackoverflow.com/a/196510/1422096)... – Basj Dec 04 '16 at 01:24
  • Thank you! Your answer helped me in 2023! 15 years have passed! – Aleksandr Jan 13 '23 at 13:33
88

Update 2019: Using Fetch:

fetch('http://localhost/foo.txt')
  .then(response => response.text())
  .then((data) => {
    console.log(data)
  })

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API

Dave Everitt
  • 17,193
  • 6
  • 67
  • 97
Vic
  • 8,261
  • 6
  • 42
  • 55
  • 4
    Yes Fetch is a (recent) standard, not a proprietary extension. – Laurent Caillette Feb 04 '19 at 10:18
  • 2
    It's 2019, and fetch is a thing of beauty. This is THE way for all modern browsers, including Samsung Internet, which just caught up… – Dave Everitt Apr 18 '19 at 15:21
  • A compact and working code, Vic, thanks you. In order to achieve error handling, would it be possible to put some `response.ok` (or equivalent) somewhere in your code? I am not very experienced on `fetch`, so I don't know the exact place to set it. – Sopalajo de Arrierez Dec 02 '19 at 19:05
  • Great solution. This was super easy even for a complete beginner. Stored in variable instead of console.log in last step, now can use anywhere. – AveryFreeman May 01 '20 at 21:53
  • 1
    Inside an `async` function, you can do `const text = await fetch(url).then($ => $.text())` to flatten out the callback. – Carl Smith Aug 10 '20 at 02:02
  • This give me an error. Uncaught (in promise) DOMException: The operation was aborted. – JD- Apr 01 '23 at 13:20
  • Edit- Nevermind, my pathing was wrong. missing a / – JD- Apr 01 '23 at 13:30
43

If you only want a constant string from the text file, you could include it as JavaScript:

// This becomes the content of your foo.txt file
let text = `
My test text goes here!
`;
<script src="foo.txt"></script>
<script>
  console.log(text);
</script>

The string loaded from the file becomes accessible to JavaScript after being loaded. The `(backtick) character begins and ends a template literal, allowing for both " and ' characters in your text block.

This approach works well when you're attempting to load a file locally, as Chrome will not allow AJAX on URLs with the file:// scheme.

A.R.
  • 15,405
  • 19
  • 77
  • 123
Erik Uggeldahl
  • 1,076
  • 11
  • 23
  • 1
    This would be a really slick solution. But template literal is not supported in IE11 and the "let" variable would be out of scope when inside a function block, so this implementation is fraught with peril - beware. – Neville Jan 26 '18 at 16:59
  • 1
    At this point even Microsoft is about to retire IE, and scope can be simplified by making it a function that returns the string instead of setting a variable using 'let' – Paul Slocum Jan 14 '21 at 17:45
22

Update 2020: Using Fetch with async/await

const response = await fetch('http://localhost/foo.txt');
const data = await response.text();
console.log(data);

Note that await can only be used in an async function. A longer example might be

async function loadFileAndPrintToConsole(url) {
  try {
    const response = await fetch(url);
    const data = await response.text();
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

loadFileAndPrintToConsole('https://threejsfundamentals.org/LICENSE');
gman
  • 100,619
  • 31
  • 269
  • 393
  • 1
    Well, its all fine except the fact that the origin requires to have cors, which isn't necessarily enabled or suitable for a lot of them. – Lakshaya U. Aug 21 '21 at 10:00
  • 1
    That's like saying Q: "how do you take money out of a bank" A: "Go into the bank and write a check for cash". You: "That's all fine except if I want to take money from someone else's account that requires a power of attorney but I don't have one for most accounts". CORS is there for a reason. It's up to the server to decide if you have permission to read the resource or not. – gman Aug 21 '21 at 10:14
  • Yup. However AJAX is better for the sake of non-cors origins. – Lakshaya U. Aug 21 '21 at 10:53
  • 1
    XMLHttpRequest has the same restrictions – gman Aug 22 '21 at 18:55
8

This should work in almost all browsers:

var xhr=new XMLHttpRequest();
xhr.open("GET","https://12Me21.github.io/test.txt");
xhr.onload=function(){
    console.log(xhr.responseText);
}
xhr.send();

Additionally, there's the new Fetch API:

fetch("https://12Me21.github.io/test.txt")
.then( response => response.text() )
.then( text => console.log(text) )
Riccardo Volpe
  • 1,471
  • 1
  • 16
  • 30
12Me21
  • 992
  • 10
  • 22
7

One thing to keep in mind is that Javascript runs on the client, and not on the server. You can't really "load a file" from the server in Javascript. What happens is that Javascript sends a request to the server, and the server sends back the contents of the requested file. How does Javascript receive the contents? That's what the callback function is for. In Edward's case, that is

    client.onreadystatechange = function() {

and in danb's case, it is

 function(data) {

This function is called whenever the data happen to arrive. The jQuery version implicitly uses Ajax, it just makes the coding easier by encapsulating that code in the library.

atmelino
  • 2,887
  • 2
  • 20
  • 15
2

When working with jQuery, instead of using jQuery.get, e.g.

jQuery.get("foo.txt", undefined, function(data) {
    alert(data);
}, "html").done(function() {
    alert("second success");
}).fail(function(jqXHR, textStatus) {
    alert(textStatus);
}).always(function() {
    alert("finished");
});

you could use .load which gives you a much more condensed form:

$("#myelement").load("foo.txt");

.load gives you also the option to load partial pages which can come in handy, see api.jquery.com/load/.

yvesonline
  • 4,609
  • 2
  • 21
  • 32
1
<!DOCTYPE html> <html> <body id="ibody">
<script>

fetch('http://localhost/myFolder/myFile.txt')
.then(response => response.text())
.then((data) => {ibody.innerHTML= data})

// data is the variable you want

</script> </body>  </html>