Node.js có được phần mở rộng tập tin


209

Tôi đang tạo một chức năng tải lên tệp trong node.js với express 3.

Tôi muốn lấy phần mở rộng tập tin của hình ảnh. vì vậy tôi có thể đổi tên tập tin và sau đó nối thêm phần mở rộng tập tin vào nó.

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

Làm cách nào tôi có thể mở rộng hình ảnh trong node.js?



3
Đó không phải là câu hỏi về loại mime, tôi muốn phần mở rộng tập tin
georgesamper

Câu trả lời:


472

Tôi tin rằng bạn có thể làm như sau để có được phần mở rộng của tên tệp.

var path = require('path')

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

54
Chỉ cần cẩn thận, nó sẽ chỉ lấy các ký tự sau dấu chấm cuối cùng, vì vậy tên tệp app.css.gzsẽ chỉ trở lại .gzvà không .css.gz, có thể hoặc không thể là những gì bạn muốn.
xentek

18
Trong trường hợp đó, chỉ cần sử dụngfilename.split('.').pop();
Aamir Afridi

12
@AamirAfridi Điều đó trả về cùng một chuỗi mà không cần ..
không xác định

13
Cố gắng 'filename.css.gz'.split('.').slice(1).join('.')để có được tất cả các tiện ích mở rộng
Trevor

10
Nói chung phần mở rộng là cái cuối cùng. Và khi chúng ta đang mong đợi nhiều hơn một, như tar.gz chẳng hạn. tốt hơn hết là kiểm tra xem cuối cùng nó có tồn tại hay không. sử dụng regex chẳng hạn. "tar.gz $" hoặc bằng cách xây dựng một chức năng làm điều đó. như kiểm tra điều đó từ cuối và quay lại và xem nó có khớp hoàn toàn không. và bạn sẽ có chức năng đó kiểm tra phần mở rộng. TẠI SAO? bởi vì những gì về các tệp như jone.lastTest.654654556.tar.gz ở đây, tiện ích mở rộng được mong đợi là tar.gz nhưng nếu bạn áp dụng bất kỳ chức năng nào có dạng chấm thứ 1, nó sẽ không hoạt động như bạn có thể thấy
Mohamed Allal 14/2/18

33

Cập nhật

Vì câu trả lời ban đầu, extname () đã được thêm vào pathmô-đun, xem câu trả lời của Snowfish

Câu trả lời gốc:

Tôi đang sử dụng chức năng này để có được một phần mở rộng tập tin, vì tôi không tìm thấy cách nào để làm điều đó một cách dễ dàng hơn (nhưng tôi nghĩ là có):

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

bạn phải yêu cầu 'đường dẫn' để sử dụng nó.

một phương thức khác không sử dụng mô đun đường dẫn:

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

4
Vâng, nó hoạt động. Chỉ cần nghĩ rằng sẽ có một cách dễ dàng hơn bằng cách sử dụng nút. Đây là những gì tôi đã làm:var is = fs.createReadStream(req.files.upload.path), fileType = is.path.split(/[. ]+/).pop();
georgesamper

6
Bạn thực sự chỉ nên sử dụng mô-đun đường dẫn, như câu trả lời của @ Snowfish đã chỉ ra, và không viết riêng cho bạn. Thông tin thêm: nodejs.org/api/path.html#path_path_extname_p
xentek

và những gì về khi các tập tin không hiển thị phần mở rộng ??
oldboy

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

Nếu bạn đang sử dụng express, vui lòng thêm dòng sau khi định cấu hình phần mềm trung gian (bodyParser)

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

12

Sử dụng substr()phương pháp này hiệu quả hơn nhiều so với split()&pop()

Hãy xem sự khác biệt về hiệu suất ở đây: http://jsperf.com/remove-first-character-from-opes

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

nhập mô tả hình ảnh ở đây

Cập nhật tháng 8 năm 2019 Như @xentek đã chỉ ra trong các bình luận; substr()hiện được coi là một chức năng kế thừa ( tài liệu MDN ). Bạn có thể sử dụng substring()thay thế. Sự khác biệt giữa substr()substring()là đối số thứ hai substr()là độ dài tối đa để trả về trong khi đối số thứ hai substring()là chỉ số dừng lại (không bao gồm ký tự đó). Ngoài ra, substr()chấp nhận các vị trí bắt đầu âm được sử dụng làm phần bù từ cuối chuỗi trong khi substring()không.


Hiện tại có một cảnh báo cho substrnó được coi là một chức năng kế thừa và nên tránh khi có thể - Thông tin thêm về MDN
Core972

Khi thực hiện kiểm tra chất nền (1), bạn cũng nên cân nhắc thời gian dành cho path.extname
eugenekr

11

Giải pháp này hỗ trợ truy vấn!

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

Một giải pháp đơn giản mà không cần yêu cầu giải quyết vấn đề mở rộng nhiều giai đoạn:

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

Hoặc nếu bạn không muốn dấu chấm hàng đầu:

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

Đảm bảo kiểm tra xem tệp có phần mở rộng không.


4

Tôi nghĩ rằng ánh xạ tiêu đề Kiểu nội dung trong yêu cầu cũng sẽ hoạt động. Điều này sẽ hoạt động ngay cả đối với các trường hợp khi bạn tải lên một tệp không có phần mở rộng. (khi tên tệp không có phần mở rộng trong yêu cầu)

Giả sử bạn đang gửi dữ liệu của mình bằng 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--

Ở đây tên tiêu đề Kiểu nội dung chứa loại mime của dữ liệu. Ánh xạ loại mime này vào một phần mở rộng sẽ giúp bạn mở rộng tập tin :).

Restify BodyParser chuyển đổi tiêu đề này thành thuộc tính với loại tên

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

Bạn có thể sử dụng tiêu đề này và thực hiện ánh xạ mở rộng (chuỗi con, v.v.), nhưng cũng có các thư viện đã sẵn sàng cho việc này. Dưới đây là hai kết quả hàng đầu khi tôi thực hiện tìm kiếm google

  • kịch câm
  • loại mime

và cách sử dụng của họ cũng đơn giản:

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

đoạn trên sẽ in png lên console.


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

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

var extension = arr[length-1];

1
biến chiều dài đến từ đâu?
Thiên thần S. Moreno

3
Cố gắng thêm một số lời giải thích cho câu trả lời của bạn. Bằng cách đó, OP thực sự có thể hiểu những gì bạn đã làm và tại sao bạn làm điều này. Bằng cách đó, OP có thể học hỏi từ câu trả lời của bạn, thay vì chỉ sao chép / dán nó.
Oldskool

1

path.extnamesẽ thực hiện các mẹo trong hầu hết các trường hợp. Tuy nhiên, nó sẽ bao gồm mọi thứ sau lần cuối cùng ., bao gồm chuỗi truy vấn và đoạn băm của yêu cầu http:

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

Trong những trường hợp như vậy, bạn sẽ muốn thử một cái gì đó như thế này:

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'

Lưu ý rằng các tiện ích mở rộng có nhiều thời kỳ (chẳng hạn như .tar.gz), hoàn toàn không hoạt động với path.extname.


0

Hàm sau chia tách chuỗi và trả về tên và phần mở rộng cho dù có bao nhiêu dấu chấm trong phần mở rộng. Nó trả về một chuỗi rỗng cho phần mở rộng nếu không có. Tên bắt đầu bằng dấu chấm và / hoặc khoảng trắng cũng hoạt động.

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

nhập tên miền để trả về phần mở rộng của tệp:

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

trong đó tập tin là tập tin 'tên' của mẫu



0

Hãy thử cái này

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'));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.