简体   繁体   中英

Node.js get file extension

Im creating a file upload function in node.js with express 3.

I would like to grab the file extension of the image. so i can rename the file and then append the file extension to it.

app.post('/upload', function(req, res, next) {
    var is = fs.createReadStream(req.files.upload.path),
        fileExt = '', // I want to get the extension of the image here
        os = fs.createWriteStream('public/images/users/' + req.session.adress + '.' + fileExt);
});

How can i get the extension of the image in node.js?

I believe you can do the following to get the extension of a file name.

var path = require('path')

path.extname('index.html')
// returns
'.html'

If you would like to get all extensions in a file name (eg filename.css.gz => css.gz ), try this:

const ext = 'filename.css.gz'
  .split('.')
  .filter(Boolean) // removes empty extensions (e.g. `filename...txt`)
  .slice(1)
  .join('.')

console.log(ext) // prints 'css.gz'

Update

Since the original answer, extname() has been added to the path module, see Snowfish answer

Original answer:

I'm using this function to get a file extension, because I didn't find a way to do it in an easier way (but I think there is) :

function getExtension(filename) {
    var ext = path.extname(filename||'').split('.');
    return ext[ext.length - 1];
}

you must require 'path' to use it.

another method which does not use the path module :

function getExtension(filename) {
    var i = filename.lastIndexOf('.');
    return (i < 0) ? '' : filename.substr(i);
}
// you can send full url here
function getExtension(filename) {
    return filename.split('.').pop();
}

If you are using express please add the following line when configuring middleware (bodyParser)

app.use(express.bodyParser({ keepExtensions: true}));

It's a lot more efficient to use the substr() method instead of split() & pop()

Have a look at the performance differences here: http://jsperf.com/remove-first-character-from-string

// returns: 'html'
var path = require('path');
path.extname('index.html').substr(1);

在此处输入图像描述

Update August 2019 As pointed out by @xentek in the comments; substr() is now considered a legacy function ( MDN documentation ). You can use substring() instead. The difference between substr() and substring() is that the second argument of substr() is the maximum length to return while the second argument of substring() is the index to stop at (without including that character). Also, substr() accepts negative start positions to be used as an offset from the end of the string while substring() does not.

This solution supports querystrings!

var Url = require('url');
var Path = require('path');

var url = 'http://i.imgur.com/Mvv4bx8.jpg?querystring=true';
var result = Path.extname(Url.parse(url).pathname); // '.jpg'

A simple solution without need for require which solves the multiple period extension problem:

var filename = 'file.with.long.extension';
var ext = filename.substring(filename.indexOf('.')); 
//ext = '.with.long.extension'

Or if you don't want the leading dot:

var filename = 'file.with.long.extension';
var ext = filename.substring(filename.indexOf('.')+1); 
//ext = 'with.long.extension'

Make sure to test that the file has an extension too.

You can use path.parse(path) , for example

const path = require('path');
const { ext } = path.parse('/home/user/dir/file.txt');

I do think mapping the Content-Type header in the request will also work. This will work even for cases when you upload a file with no extension. (when filename does not have an extension in the request)

Assume you are sending your data using HTTP POST:

POST /upload2 HTTP/1.1
Host: localhost:7098
Connection: keep-alive
Content-Length: 1047799
Accept: */*
Origin: http://localhost:63342
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML,    like Gecko) Chrome/51.0.2704.106 Safari/537.36
Content-Type: multipart/form-data; boundary=----   WebKitFormBoundaryPDULZN8DYK3VppPp
Referer: http://localhost:63342/Admin/index.html? _ijt=3a6a054pasorvrljf8t8ea0j4h
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,az;q=0.6,tr;q=0.4
Request Payload
------WebKitFormBoundaryPDULZN8DYK3VppPp
Content-Disposition: form-data; name="image"; filename="blob"
Content-Type: image/png


------WebKitFormBoundaryPDULZN8DYK3VppPp--

Here name Content-Type header contains the mime type of the data. Mapping this mime type to an extension will get you the file extension :).

Restify BodyParser converts this header in to a property with name type

File {
  domain: 
   Domain {
     domain: null,
     _events: { .... },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [ ... ] },
  _events: {},
  _eventsCount: 0,
  _maxListeners: undefined,
  size: 1047621,
  path: '/tmp/upload_2a4ac9ef22f7156180d369162ef08cb8',
  name: 'blob',
  **type: 'image/png'**,
  hash: null,
  lastModifiedDate: Wed Jul 20 2016 16:12:21 GMT+0300 (EEST),
  _writeStream: 
  WriteStream {
   ... },
     writable: true,
     domain: 
     Domain {
        ...
     },
      _events: {},
      _eventsCount: 0,
     _maxListeners: undefined,
     path: '/tmp/upload_2a4ac9ef22f7156180d369162ef08cb8',
     fd: null,
     flags: 'w',
     mode: 438,
     start: undefined,
     pos: undefined,
     bytesWritten: 1047621,
     closed: true } 
}

You can use this header and do the extension mapping (substring etc ...) manually, but there are also ready made libraries for this. Below two were the top results when i did a google search

  • mime
  • mime-types

and their usage is simple as well:

 app.post('/upload2', function (req, res) {
  console.log(mime.extension(req.files.image.type));
 }

above snippet will print png to console.

import extname in order to return the extension the file:

import { extname } from 'path';
extname(file.originalname);

where file is the file 'name' of form

A one liner which extends String.prototype :

Object.defineProperty(String.prototype, "ext", {get: function(x) {return this.split('.').pop()}})
str = 'fox.fbx';
str.ext

Result:

在此处输入图像描述

path.extname will do the trick in most cases. However, it will include everything after the last . , including the query string and hash fragment of an http request:

var path = require('path')
var extname = path.extname('index.html?username=asdf')
// extname contains '.html?username=asdf'

In such instances, you'll want to try something like this:

var regex = /[#\\?]/g; // regex of illegal extension characters
var extname = path.extname('index.html?username=asdf');
var endOfExt = extname.search(regex);
if (endOfExt > -1) {
    extname = extname.substring(0, endOfExt);
}
// extname contains '.html'

Note that extensions with multiple periods (such as .tar.gz ), will not work at all with path.extname .

var fileName = req.files.upload.name;

var arr = fileName.split('.');

var extension = arr[length-1];

The following function splits the string and returns the name and extension no matter how many dots there are in the extension. It returns an empty string for the extension if there is none. Names that start with dots and/or white space work also.

function basext(name) {
  name = name.trim()
  const match = name.match(/^(\.+)/)
  let prefix = ''
  if (match) {
    prefix = match[0]
    name = name.replace(prefix, '')
  }
  const index = name.indexOf('.')
  const ext = name.substring(index + 1)
  const base = name.substring(0, index) || ext
  return [prefix + base, base === ext ? '' : ext]
}

const [base, ext] = basext('hello.txt')

Try this one

const path = require('path');

function getExt(str) {
  const basename = path.basename(str);
  const firstDot = basename.indexOf('.');
  const lastDot = basename.lastIndexOf('.');
  const extname = path.extname(basename).replace(/(\.[a-z0-9]+).*/i, '$1');

  if (firstDot === lastDot) {
    return extname;
  }

  return basename.slice(firstDot, lastDot) + extname;
}

// all are `.gz`
console.log(getExt('/home/charlike/bar/file.gz'));
console.log(getExt('/home/charlike/bar/file.gz~'));
console.log(getExt('/home/charlike/bar/file.gz+cdf2'));
console.log(getExt('/home/charlike/bar/file.gz?quz=zaz'));

// all are `.tar.gz`
console.log(getExt('/home/charlike/bar/file.tar.gz'));
console.log(getExt('/home/charlike/bar/file.tar.gz~'));
console.log(getExt('/home/charlike/bar/file.tar.gz+cdf2'));
console.log(getExt('/home/charlike/bar/file.tar.gz?quz=zaz'));

const path = require('path');

function getExt(str) {
  const basename = path
    .basename(str)
    // Patch: for hidden files
    // Removes all dots at the beginning of a line
    .replace(/^(\.+)/i, '');

  const firstDot = basename.indexOf('.');
  const lastDot = basename.lastIndexOf('.');
  const extname = path.extname(basename).replace(/(\.[a-z0-9]+).*/i, '$1');

  if (firstDot === lastDot) {
    return extname;
  }

  return basename.slice(firstDot, lastDot) + extname;
}
const files = [
  '/home/charlike/bar/.hidden.tar.gz~',     // ".tar.gz"
  '/home/charlike/bar/file.tar.gz~',        // ".tar.gz"
  '/home/charlike/bar/file.tar.gz+cdf2',    // ".tar.gz"
  '/home/charlike/bar/file.tar.gz?quz=zaz', // ".tar.gz"
];

const fileAndExt = files.map((file) => [ file, getExt(file) ]);

console.log(JSON.stringify(fileAndExt, null, 2));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM