Dynamically Generating Download Files

Download Now Img

It may come as no surprise to many of you, that I love Dart. With this love, I’ve made a significant change in the way I handle some of the tasks I get on a day-to-day basis. One of the tasks which would inevitably come up is the take some kind of data or input, handle and manipulate it in some way (internally they like to call it massaging the data, but its rarely that relaxing) and create an output file (usually text).

In the past, normally I would have accomplished this by writing a little Ruby script, or even a Perl script. This often presented a few problems however. First would be that if I wrote the script on my Linux PC, then I’m the one who had to constantly be emailed the data, or generate it myself. Then e-mail off the results. It also meant that if I wasn’t in the office, it wasn’t done. So an option was to my script on a server, then any of the server admins could run the script (once I documented where it was, how to run it, etc). But it still meant that they would have to go through the same process I would need to.

Of course, the perfect solution is to just create a web-app. Before Dart, I would create a PHP page and script to upload the input information, parse it on the server and provide a download link for the results. It was better, as then at least anyone could run the scripts themselves without needing to go through me or the server admins. But there was one big problem… it was PHP.

Now with Dart, I don’t need to go through all of that, and in many cases I only need a server to host the page itself for others to access. No need to transfer the data back and forth to the server for the parsing. One of the major factors in making this easy for me is HTML5 Download Attribute.

My first step in dynamically creating a downloadable file is to create a Blob object with the contents of my file. This is really quite simple as the Blob just takes a list of parts which make up the blob, in my case, it’s usually a list of lines of the final text file. Additional arguments are the MIME encoding for the blob (or rather the final output file, such as “text/plain”), and the format of the line endings, which can be either “transparent” or “native”. Transparent will leave new line endings just as they are passed into the blob, and Native will specify that the file should use the line ending specific to the native operating environment. This means you don’t have to worry about if your user is on Linux, Mac, or Windows when downloading the file.

Next up, we need to create a Data URI which contains the data from our blob object. Again this is really easy with the Dart Url class. In particular using the createObjectUrlFromBlob() method. We just pass in our Blob and receive our URL.

The final step, involves creating our link, and assigning the various properties we need. In the example below I decided to create an entirely new element, however it’s equally valid to grab a link already in the page and just update its properties and maybe toggle the visibility. In particular we need to set the download property. This will be the filename that is automatically used to save the file on the user’s computer. And we need to set the href property to be the Blob URL we just created.

You can see all of this in action below:

test.dart

import 'dart:html';

void main() {
  // Our imaginary dynamically generated data
  List body = [ 'This list is the text\n',
                'which our final output\n',
                'file will contain.\n\n',
                "It's really nothing\n",
                'special in any way.\n',
                'Normally this stuff would\n',
                'be dynamically generated\n',
                'in some way.\n\n'];
  
  // Create a new blob from the data.
  Blob blob = new Blob(body, 'text/plain', 'native');
  // Create a data:url which points to that data.
  String url = Url.createObjectUrlFromBlob(blob);
  // Create a link to navigate to that data and download it.
  AnchorElement link = new AnchorElement()
      ..href = url
      ..download = 'random_file.txt'
      ..text = 'Download Now!';
  
  // Insert the link into the DOM.
  var p = querySelector('#text');
  p.append(link);
}

test.html

<!DOCTYPE html>

<html>
  <head>
  	<meta charset="utf-8">
  	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    
  </head>
 
  <body>   
    <p id="text"></p>
    <script type="application/dart" src="test.dart"></script>
    <!-- for this next line to work, your pubspec.yaml file must have a dependency on 'browser' -->
    <script src="packages/browser/dart.js"></script>
  </body>
</html>
This entry was posted in Dart and tagged , , , . Bookmark the permalink.

Have Something To Add?

Loading Facebook Comments ...
Loading Disqus Comments ...