Node.js obter extensão de arquivo


209

Estou criando uma função de upload de arquivo no node.js com o express 3.

Gostaria de pegar a extensão do arquivo da imagem. para que eu possa renomear o arquivo e depois anexá-lo à extensão.

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);
});

Como posso obter a extensão da imagem no node.js?



3
Isso não é pergunta sobre mime-types, eu quero a extensão do arquivo
georgesamper

Respostas:


473

Eu acredito que você pode fazer o seguinte para obter a extensão de um nome de arquivo.

var path = require('path')

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

54
Apenas tome cuidado, pois ele só pegará os caracteres após o último ponto; portanto, nomes de arquivos como app.css.gzretornarão apenas .gze não .css.gz, o que pode ou não ser o que você deseja.
xentek 23/02

18
Nesse caso, basta usarfilename.split('.').pop();
Aamir Afridi

12
@AamirAfridi Isso retorna a mesma string apenas sem o ..
undefined

13
Tente 'filename.css.gz'.split('.').slice(1).join('.')obter todas as extensões
Trevor

10
Geralmente a extensão é a última. E para quando esperamos mais de um, como o tar.gz, por exemplo. é melhor verificar se existe no final ou não. usando regex por exemplo. "tar.gz $" ou criando uma função que faça isso. como verificar isso do final e voltar e ver se ele combina totalmente. e você terá essa função que verifica a extensão. PORQUE? porque o que acontece com arquivos como jone.lastTest.654654556.tar.gz aqui a extensão que se espera é tar.gz, mas se você aplicar qualquer função que dão forma 1 ponto, não vai funcionar como você pode ver
Mohamed Allal

33

Atualizar

Como a resposta original extname () foi adicionada ao pathmódulo, consulte Resposta do Snowfish

Resposta original:

Estou usando esta função para obter uma extensão de arquivo, porque não encontrei uma maneira de fazê-lo de uma maneira mais fácil (mas acho que existe):

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

você deve exigir 'caminho' para usá-lo.

outro método que não usa o módulo de caminho:

function getExtension(filename) {
    var i = filename.lastIndexOf('.');
    return (i < 0) ? '' : filename.substr(i);
}

4
Sim, isso funciona. Apenas pensei que haveria uma maneira mais fácil de usar o nó. Isto é o que eu fiz:var is = fs.createReadStream(req.files.upload.path), fileType = is.path.split(/[. ]+/).pop();
georgesamper

6
Você realmente deve usar o módulo path, como a resposta do @ Snowfish apontou, e não escrever a sua. Mais informações: nodejs.org/api/path.html#path_path_extname_p
xentek

e quando os arquivos não estão mostrando extensões?
oldboy

19
// you can send full url here
function getExtension(filename) {
    return filename.split('.').pop();
}

Se você estiver usando express, adicione a seguinte linha ao configurar o middleware (bodyParser)

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

12

É muito mais eficiente usar o substr()método em vez de split()&pop()

Veja as diferenças de desempenho aqui: http://jsperf.com/remove-first-character-from-string

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

insira a descrição da imagem aqui

Atualização em agosto de 2019 Como apontado por @xentek nos comentários; substr()agora é considerado uma função herdada ( documentação MDN ). Você pode usar em seu substring()lugar. A diferença entre substr()e substring()é que o segundo argumento de substr()é o tamanho máximo a ser retornado, enquanto o segundo argumento de substring()é o índice no qual parar (sem incluir esse caractere). Além disso, substr()aceita posições iniciais negativas para serem usadas como um deslocamento do final da string, enquanto substring()não.


Há um aviso agora para substrele é considerado uma função legado e deve ser evitado quando possível - Mais informações sobre MDN
Core972

Ao fazer o teste substr (1), você também deve levar em consideração o tempo gasto no caminho.extname
eugenekr

11

Esta solução suporta 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'

6

Uma solução simples, sem necessidade de exigir, que resolva o problema de extensão de vários períodos:

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

Ou se você não quiser o ponto inicial:

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

Certifique-se de testar se o arquivo também possui uma extensão.


4

Eu acho que o mapeamento do cabeçalho Content-Type na solicitação também funcionará. Isso funcionará mesmo nos casos em que você enviar um arquivo sem extensão. (quando o nome do arquivo não tiver uma extensão na solicitação)

Suponha que você esteja enviando seus dados usando 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--

Aqui, o nome Content-Type header contém o tipo MIME dos dados. O mapeamento desse tipo de mime para uma extensão fornecerá a extensão do arquivo :).

Restify BodyParser converte esse cabeçalho em uma propriedade com o tipo de nome

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 } 
}

Você pode usar esse cabeçalho e fazer o mapeamento de extensão (substring etc ...) manualmente, mas também existem bibliotecas prontas para isso. Abaixo dois foram os principais resultados quando eu fiz uma pesquisa no google

  • mímica
  • tipos mímicos

e seu uso também é simples:

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

o snippet acima imprimirá png no console.


2
var fileName = req.files.upload.name;

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

var extension = arr[length-1];

1
de onde vem a variável length?
Angel S. Moreno

3
Tente adicionar alguma explicação à sua resposta. Dessa forma, o OP pode realmente entender o que você fez e por que você fez isso. Dessa forma, o OP pode aprender com sua resposta, em vez de apenas copiar / colar.
Oldskool

1

path.extnamefará o truque na maioria dos casos. No entanto, incluirá tudo após o último ., incluindo a sequência de caracteres de consulta e o fragmento de hash de uma solicitação http:

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

Nesses casos, convém tentar algo como isto:

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'

Observe que extensões com vários períodos (como .tar.gz), não funcionarão com path.extname.


0

A função a seguir divide a sequência e retorna o nome e a extensão, não importa quantos pontos existam na extensão. Retorna uma string vazia para a extensão, se não houver nenhuma. Nomes que começam com pontos e / ou espaço em branco também funcionam.

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')

0

importe extname para retornar a extensão do arquivo:

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

onde arquivo é o arquivo 'nome' do formulário


0

Você pode usar path.parse (path) , por exemplo

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

0

Tente este

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'));
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.