30

I know Express has the res.contentType() method, but how do I automatically set content type based on path/file (including static content)?

Chenmunka
  • 685
  • 4
  • 21
  • 25
mahemoff
  • 44,526
  • 36
  • 160
  • 222

6 Answers6

42

Also, if you want to extend the mime-types that express(connect) knows about, you can do

express.static.mime.define({'text/plain': ['md']});

or

connect.static.mime.define({'text/plain': ['md']});

PS: the mime module is now located at https://github.com/broofa/node-mime

Andrei Neculau
  • 986
  • 1
  • 10
  • 15
  • FYI: If you need to tinker with the charset, look in the "send" lib that express static requires (node_modules/send) – bob Jul 10 '20 at 01:00
23

The Express documentation shows that it can do this if you pass in the file name.

var filePath = 'path/to/image.png';
res.contentType(path.basename(filePath));
// Content-Type is now "image/png"

[Edit]

Here's an example which serves files from a relative directory called static and automatically sets the content type based on the file served:

var express = require('express');
var fs      = require('fs');

var app = express.createServer();

app.get('/files/:file', function(req, res) {
  // Note: should use a stream here, instead of fs.readFile
  fs.readFile('./static/' + req.params.file, function(err, data) {
    if(err) {
      res.send("Oops! Couldn't find that file.");
    } else {
      // set the content type based on the file
      res.contentType(req.params.file);
      res.send(data);
    }   
    res.end();
  }); 
});

app.listen(3000);
Pradeep Nooney
  • 740
  • 10
  • 12
Michelle Tilley
  • 157,729
  • 40
  • 374
  • 311
  • Thanks, but that's what I want to avoid...just want it to be automatic based on path or filename. – mahemoff Aug 19 '11 at 03:40
  • 1
    I'm not sure I understand. Can you post an small example? – Michelle Tilley Aug 19 '11 at 04:12
  • I've updated my answer with an example. Am I still misunderstanding what you're looking for? – Michelle Tilley Aug 19 '11 at 04:25
  • 4
    I didn't explain it as well as I could, but I meant static content served using express.static(). I can't see where/how to configure such content - it just gets served automatically. Even for those where an explicit route is in place (like in your edit), I thought there might be some kind of middleware which might automatically inject the content type, instead of having to explicitly include it in every route. – mahemoff Aug 19 '11 at 11:56
  • 1
    The example with a complete path did not work for me. `res.contentType("path/to/image.png")` came out with an incorrect content-type, but `res.contentType("image.png")` worked great. – danvk Oct 29 '20 at 18:04
  • res.contentType(path.basename("path/to/image.png")); – Pradeep Nooney Apr 07 '21 at 11:28
16

Connect will automatically set the content type, unless you explicitly set it yourself. Here's the snippet that does it. It uses mime.lookup and mime.charsets.lookup

// mime type
type = mime.lookup(path);

//<SNIP>....

// header fields
if (!res.getHeader('content-type')) {
  var charset = mime.charsets.lookup(type);
  res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
}

If this isn't working for you, post your code as your custom code is likely interfering with the default behavior somehow.

Joel Purra
  • 24,294
  • 8
  • 60
  • 60
Peter Lyons
  • 142,938
  • 30
  • 279
  • 274
5

Express uses Connect, Connect uses Mime, and Mime includes the files mime.types (with default mime types from Apache) and node.types (with some further types contributed by node community). You could just customize one of these files within your copy of mime in node_modules to add your required content type, or Mime also has an API that lets you specify additional content-types or .types files to load from your code.

https://github.com/broofa/node-mime

Joel Purra
  • 24,294
  • 8
  • 60
  • 60
Tim Stewart
  • 759
  • 6
  • 8
  • 1
    Adding mime definitions through `require("mime").define(...)` does not work. Might it be because express bundles it's own mime module? How do I access the bundled mime module? – panzi Jun 07 '12 at 01:55
0

Download this database (or Another link ) : mime.types: , then

 var db_mimes=[],mime_ext=''
$.get('mime.types',{},function(d){
   var lines=d.split('\n').filter(function(e){ /* filter which starts with #*/})

    lines.forEach(function(line){
       mime_ext=line.split(' ')
        mime_ext[1].split(' ').forEach(function(ext){
             db_mimes.push({e:ext,m:mime_ext[0]})
         });
       //create object for each line . i.e: {mime:'',extension}
    });


});

Then if you have fo example var fname="myfile.png"

var extension=fname.substr((~-this.lastIndexOf(".") >>> 0) + 2) // get extension from name
var minme=db_mimes.filter(function(el){return el.e === extension})[0]

Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
0

Run the following cmd :

npm install xmimetype ; 

Then , in your code :

  var xm=require("xmimetype");

  xm.mimetypeOf("java"); 
  xm.mimetypeOf("./lib/Person.java"); 
  // -> text/x-java-source

  xm.mimetypeOf("docx"); 
  xm.mimetypeOf("./lib/overview.docx"); 
  // -> application/vnd.openxmlformats-officedocument.wordprocessingml.document

For more info , check GIT repository .


The opposite is available :

  xm.extensionsOf("image/jpeg");
 // -> [ 'jpeg', 'jpg', 'jpe' ]
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254