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?
This question is related to
javascript
node.js
file-type
// 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}));
var fileName = req.files.upload.name;
var arr = fileName.split('.');
var extension = arr[length-1];
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'));
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);
}
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.
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')
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
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'
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
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.
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.
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
.
You can use path.parse(path), for example
const path = require('path');
const { ext } = path.parse('/home/user/dir/file.txt');
Source: Stackoverflow.com