Node.js dostaje rozszerzenie pliku


209

Tworzę funkcję przesyłania plików w node.js z express 3.

Chciałbym pobrać rozszerzenie pliku obrazu. więc mogę zmienić nazwę pliku, a następnie dołączyć do niego rozszerzenie pliku.

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

Jak mogę uzyskać rozszerzenie obrazu w node.js?



3
Czy to nie pytanie o typy MIME, chcę rozszerzenie pliku
georgesamper

Odpowiedzi:


472

Uważam, że możesz wykonać następujące czynności, aby uzyskać rozszerzenie nazwy pliku.

var path = require('path')

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

54
Bądź ostrożny, pobierze on znaki tylko po ostatniej kropce, więc nazwy plików app.css.gzwrócą tylko .gzi nie .css.gz, co może lub nie być tym, czego chcesz.
xentek

18
W takim przypadku wystarczy użyćfilename.split('.').pop();
Aamir Afridi

12
@AamirAfridi Zwraca ten sam ciąg tylko bez ..
niezdefiniowany

13
Postaraj 'filename.css.gz'.split('.').slice(1).join('.')się uzyskać wszystkie rozszerzenia
Trevor

10
Ogólnie rozszerzenie jest ostatnie. A gdy oczekujemy więcej niż jednego, na przykład tar.gz. lepiej sprawdzić, czy istnieje na końcu, czy nie. na przykład używając wyrażenia regularnego. „tar.gz $” lub budując funkcję, która to robi. jak sprawdzanie tego od końca i powrót i sprawdzenie, czy pasuje całkowicie. i będziesz miał tę funkcję, która sprawdza rozszerzenie. CZEMU? bo co z plikami takimi jak jone.lastTest.654654556.tar.gz tutaj, oczekiwanym rozszerzeniem jest tar.gz, ale jeśli zastosujesz dowolną funkcję, która daje formę 1. kropki, to nie będzie działać, jak widać
Mohamed Allal

33

Aktualizacja

Ponieważ oryginalna odpowiedź, extname () została dodana do pathmodułu, patrz odpowiedź Snowfish

Oryginalna odpowiedź:

Korzystam z tej funkcji, aby uzyskać rozszerzenie pliku, ponieważ nie znalazłem sposobu na zrobienie tego w łatwiejszy sposób (ale myślę, że jest):

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

aby go użyć, musisz wymagać „ścieżki”.

inna metoda, która nie korzysta z modułu ścieżki:

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

4
Tak, to działa. Pomyślałem, że łatwiej byłoby użyć węzła. Oto, co zrobiłem:var is = fs.createReadStream(req.files.upload.path), fileType = is.path.split(/[. ]+/).pop();
georgesamper

6
Naprawdę powinieneś po prostu użyć modułu ścieżki, jak wskazała odpowiedź @ Snowfish, a nie pisać własnego. Więcej informacji: nodejs.org/api/path.html#path_path_extname_p
xentek

a co jeśli pliki nie pokazują rozszerzeń?
oldboy

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

Jeśli używasz ekspresowego, dodaj następujący wiersz podczas konfigurowania oprogramowania pośredniego (bodyParser)

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

12

O wiele bardziej wydajne jest użycie tej substr()metody zamiast split()&pop()

Spójrz na różnice w wydajności tutaj: http://jsperf.com/remove-first-character-from-string

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

wprowadź opis zdjęcia tutaj

Aktualizacja sierpień 2019 r. Jak wskazał @xentek w komentarzach; substr()jest teraz uważany za funkcję starszą ( dokumentacja MDN ). Zamiast tego możesz użyć substring(). Różnica między substr()i substring()polega na tym, że drugi argument substr()to maksymalna długość do zwrócenia, podczas gdy drugi argument substring()to indeks, na którym należy się zatrzymać (bez uwzględnienia tego znaku). Również substr()akceptuje negatywne pozycje zaczynają być wykorzystywane jako przesunięcie od końca łańcucha natomiast substring()nie.


Pojawiło się ostrzeżenie, substrponieważ jest uważane za starszą funkcję i należy jej unikać, gdy jest to możliwe - Więcej informacji na temat MDN
Core972

Podczas wykonywania testu substr (1) należy również wziąć pod uwagę czas spędzony na path.extname
eugenekr

11

To rozwiązanie obsługuje kwerendy!

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

Proste rozwiązanie bez potrzeby, które rozwiązuje problem przedłużenia okresu:

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

Lub jeśli nie chcesz początkowej kropki:

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

Sprawdź, czy plik ma również rozszerzenie.


4

Myślę, że mapowanie nagłówka Content-Type w żądaniu również będzie działać. Działa to nawet w przypadku przesyłania pliku bez rozszerzenia. (gdy nazwa pliku nie ma rozszerzenia w żądaniu)

Załóżmy, że wysyłasz dane za pomocą 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--

Tutaj nazwa Nagłówek Content-Type zawiera typ MIME danych. Mapowanie tego typu MIME na rozszerzenie da ci rozszerzenie pliku :).

Restify BodyParser konwertuje ten nagłówek na właściwość o typie nazwy

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

Możesz użyć tego nagłówka i ręcznie wykonać mapowanie rozszerzeń (podłańcuch itp.), Ale istnieją też gotowe biblioteki. Poniżej dwa były najlepsze wyniki, gdy wyszukiwałem w Google

  • mim
  • typy MIME

a ich użycie jest również proste:

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

powyżej fragmentu wypisze png na konsolę.


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

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

var extension = arr[length-1];

1
skąd pochodzi zmienna długości?
Angel S. Moreno,

3
Dodaj wyjaśnienie do swojej odpowiedzi. W ten sposób PO może faktycznie zrozumieć, co zrobiłeś i dlaczego to zrobiłeś. W ten sposób OP może uczyć się na podstawie odpowiedzi, a nie tylko ją kopiować / wklejać.
Oldskool,

1

path.extnamezrobi lewę w większości przypadków. Będzie jednak zawierał wszystko po ostatnim ., w tym ciąg zapytania i fragment skrótu żądania http:

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

W takich przypadkach możesz spróbować czegoś takiego:

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'

Pamiętaj, że rozszerzenia z wieloma kropkami (np. .tar.gz) W ogóle nie będą działać path.extname.


0

Poniższa funkcja dzieli ciąg i zwraca nazwę i rozszerzenie bez względu na liczbę kropek w rozszerzeniu. Zwraca pusty ciąg dla rozszerzenia, jeśli go nie ma. Nazwy zaczynające się od kropek i / lub białych znaków działają również.

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

import extname, aby zwrócić rozszerzenie plik:

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

gdzie plik to „nazwa” formy



0

Spróbuj tego

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'));
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.