Benny
Benny

Reputation: 3917

Nodejs Express Send File

I am trying to send a file's content to the client in my request, but the only documentation Express has is it's download function which requires a physical file; the file I am trying to send comes from S3, so all I have is the filename and content.

How do I go about sending the content of the file and appropriate headers for content type and filename, along with the file's content?

For example:

files.find({_id: id}, function(e, o) {
  client.getObject({Bucket: config.bucket, Key: o.key}, function(error, data) {
    res.send(data.Body);
  });
});

Upvotes: 3

Views: 7733

Answers (2)

Noah
Noah

Reputation: 34333

This is a great situation to use streams. Use the knox library to simplify things. Knox should take care of setting the needed headers to pipe files to the client

var inspect = require('eyespect').inspector();
var knox = require('knox');
var client = knox.createClient({
  key: 's3KeyHere'
  , secret: 's3SecretHere'
  , bucket: 's3BucketHer'
});
/**
 * @param {Stream} response is the response handler provided by Express
 **/
function downloadFile(request, response) {
  var filePath = 's3/file/path/here';
  client.getFile(filePath, function(err, s3Response) {
    s3Response.pipe(response);
    s3Response.on('error', function(err){
      inspect(err, 'error downloading file from s3');
    });

    s3Response.on('progress', function(data){
      inspect(data, 's3 download progress');
    });
    s3Response.on('end', function(){
      inspect(filePath, 'piped file to remote client successfully at s3 path');
    });
  });
}

npm install knox eyespect

Upvotes: 0

freakish
freakish

Reputation: 56517

The type of file depends on the file obviously. Have a look at this:

http://en.wikipedia.org/wiki/Internet_media_type

If you know what exactly is your file, then assign one of these to response ( not mandatory though ). You should also add the length of the file to response ( if it is possible, i.e. if it is not a stream ). And if you want it to be downloadable as an attachment, then add Content-Disposition header. So all in all you only need to add this:

var filename = "myfile.txt";
res.set({
    "Content-Disposition": 'attachment; filename="'+filename+'"',
    "Content-Type": "text/plain",
    "Content-Length": data.Body.length
});

NOTE: I'm using Express 3.x.

EDIT: Actually Express is smart enough to count content length for you, so you don't have to add Content-Length header.

Upvotes: 7

Related Questions