9

I'm using Koa as a webserver to serve my Polymer application. Upon pressing a button in the frontend localhost:3000/export is called. I would like to deliver a file-download to the client after packing the some files to a zip-archive.

How to do this in Koa.js?

Here's an example on how to do it in Express (another option would be the download-helper

app.get('/export', function(req, res){

  var path = require('path');
  var mime = require('mime');

  var file = __dirname + '/upload-folder/dramaticpenguin.MOV';

  var filename = path.basename(file);
  var mimetype = mime.lookup(file);

  res.setHeader('Content-disposition', 'attachment; filename=' + filename);
  res.setHeader('Content-type', mimetype);

  var filestream = fs.createReadStream(file);
  filestream.pipe(res);
});

I'm looking for something like this:

router.post('/export', function*(){
  yield download(this, __dirname + '/test.zip')
})
Hedge
  • 16,142
  • 42
  • 141
  • 246

4 Answers4

26

For anyone else who sees this in the future, it's worth mentioning that there is a built in attachment method on the response object that you can use to set the Content-Disposition to attachment with a specified filename. So you can do this:

this.attachment('hello.txt')

And it would be the same thing as the following:

this.set('Content-disposition', 'attachment; filename=hello.txt')

For Koa 2:

ctx.attachment('hello.txt')
Saad
  • 49,729
  • 21
  • 73
  • 112
25

You should be able to simple set this.body to the file stream

this.body = fs.createReadStream(__dirname + '/test.zip');

then set the response headers as appropriate.

this.set('Content-disposition', 'attachment; filename=' + filename);
this.set('Content-type', mimetype);
James Moore
  • 1,881
  • 14
  • 18
3

Browser default behaviour is to display the file, not to download it. To enforce download you need to do this:

this.header("Content-Type", "application/force-download")
this.header('Content-disposition', 'attachment; filename=' + filename);
Valera
  • 2,665
  • 2
  • 16
  • 33
2

Bit of a different file download example with error checking, using Node with Koa 2. I am not sure if it is necessary to destroy the stream afterwards as described here https://github.com/jshttp/content-disposition#options

router.get('/downloads/:version/:file', async function(ctx) {
  const fileName = `${__dirname}/downloads/${ctx.params.version}/${ctx.params.file}`;
  try {
    if (fs.existsSync(fileName)) {
      ctx.body = fs.createReadStream(fileName);
      ctx.attachment(fileName);
    } else {
      ctx.throw(400, "Requested file not found on server");
    }
  } catch(error) {
    ctx.throw(500, error);
  }  
});

In browser sample: https://myserver.com/downloads/1.0.0/CoolAppFile.zip

leoncc
  • 233
  • 3
  • 6