Downloading a file

This recipe shows you the simplest ways to download a file through code, first in a command-line application and then from a web application. As an example, we download the front page of the Learning Dart website from http://learningdart.org.

Getting ready

A client program (be it web or command-line) receives content, such as files or web pages, from a web server using the HTTP protocol. The dart:html and dart:io package provides us with the basic classes we need to do this, which are as follows:

  • The Uriclass class (from dart:core) has all we need to parse, encode, and decode web addresses; the method Uri.parse is often used
  • The HttpRequest class (from dart:html) has the getString method to fetch a file from a URL
  • The HttpClientclass class (from dart:io) has all kinds of methods, such as get and post, to send a request (class HttpClientRequest) to a web server and get a response (class HttpClientResponse) back

How to do it...

  1. For a web app, this is shown in download_string.dart, which is started from download_string.html (these files can be found in the download_file project) as shown in the following code:
    import 'dart:html';
    
    main() {
      HttpRequest.getString('http://learningdart.org')
      .then(processString)
      .catchError(print);
    }
    
    processString(str) {
      print(str);
    }
  2. For a command-line app in the program download_file.dart, we see the basic mechanism of how to do this for a command-line app as follows:
    import 'dart:io';
    import 'dart:convert';
    
    var client;
    
    main() {
      var url = Uri.parse('http://learningdart.org'),
      client = new HttpClient();
      client.getUrl(url)
      .then((HttpClientRequest req) => req.close())
      .then((HttpClientResponse resp) => writeToFile(resp));
    }
    
    writeToFile(resp) {
      resp.transform(UTF8.decoder)
      .toList().then((data) {
        var body = data.join(''),
        var file = new File('dart.txt'),
        file.writeAsString(body).then((_) {
        client.close();
        });
      });
    }

How it works...

For a web app, we use the getString method on HttpRequest to fetch the file from the URL as one big string, which is asynchronously passed to processString. It could do just about anything with the string it gets back, for example, if it were a JSON or XML string, we could parse this and get data out of it to show on our web page. So HttpRequestcan is used to fetch data over HTTP and FTP protocols from a URL, without producing complete web page updates. This is, in fact, the way to make AJAX calls (or XMLHttpRequest) and as a consequence, partial page updates. We will use it in the following recipe to fetch a large blob file.

Note

Don't confuse this class with another class with the same name HttpRequest from dart:io, which must be used in server-side applications (we will use it extensively in the recipes of the following chapter). A web server, or more formally, an HTTP server, that listens for HTTP requests coming in on a specific host and port, generates such an object for each request it receives.

For a command-line app, first we transform the web address string to a Uri object with the static method parse. Then we make an HttpClient object and invoke the getUrl request on URL (the Uri object). This works in two steps, each returning a Future, which are:

  • The first .then completes with a request object that has been made but not sent yet. In the callback, you can still change or add to the request headers or the body. A call to close sends the request to the server. This step serves to make the request and send it.
  • The second .then completes when the response object is received from the server, and you can access headers and the body (the body is available as a stream). This step serves to process the response; here, we call writeToFile.

    Note

    If there is a body, it must be processed. Avoid memory leaks by calling the method drain().

In writeToFile, we read the response data, transforming it from UTF-8 to a string (helped by the join method that transforms the list into a string), and write it to a file with writeAsString. When this finishes, the HttpClient object is closed; this releases the network connections that have been made.

There's more...

The following are some variations to accomplish the same thing for a command-line app:

Using pipe

The .then variable in the command line can be simplified to the following:

.then((HttpClientResponse resp) => resp.pipe(new File('dart.txt').openWrite()));

The pipe method on the response object can send the stream immediately to the file to be written. This will perform better when downloading bigger files.

Using the http package

An even more simplified approach can be taken using the http package by the Dart team, which was made to facilitate coding requests and responses (see download_file2.dart). Have a look at the following code:

import 'dart:io';
import 'package:http/http.dart' as http;

main() {
  var url = Uri.parse('http://learningdart.org'),
  http.get(url).then((response) {
  new File('dart.txt').writeAsBytes(response.bodyBytes);
  });
}

See also

  • See the Writing to a file recipe for information on the writeAsBytes method
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset