Giới hạn định dạng tệp khi sử dụng <kiểu đầu vào = Tập tin Tập tin >>?


667

Tôi muốn hạn chế loại tệp có thể được chọn từ trình chọn tệp hệ điều hành gốc khi người dùng nhấp vào nút Duyệt trong <input type="file">phần tử trong HTML. Tôi có cảm giác đó là không thể, nhưng tôi muốn biết nếu có một giải pháp. Tôi chỉ muốn duy trì HTML và JavaScript; xin vui lòng không có Flash.


1
Nó có thể dễ dàng với PHP, nhưng tôi không biết liệu bạn có thể sử dụng nó không nên tôi sẽ không đăng mã.
Latox

2
Tôi có thể, nhưng tôi có một giải pháp làm việc với JavaScript - nó loại bỏ sự khó chịu khi tải lên một tệp sau đó nhận được "Tệp sai!" lỗi.
Bojangles

Ngoài ra, hãy xem thêm câu hỏi gần đây: stackoverflow.com/questions/181214/ từ
Barshe Roussy

Một điều cần lưu ý là mặc dù nó không tuyệt vời để xác thực, chấp nhận sẽ giới hạn các tệp hiển thị ở những tệp được chấp nhận trong khi người dùng đang duyệt chúng (ít nhất là trong một số trình duyệt ...). Vì vậy, đây là một tính năng công thái học UI hơn là một tính năng xác nhận.
Barshe Roussy

Câu trả lời:


1119

Nói đúng ra, câu trả lời là không . Nhà phát triển không thể ngăn người dùng tải lên các tệp thuộc bất kỳ loại hoặc phần mở rộng nào.

Tuy nhiên, thuộc tính chấp nhận<input type = "file"> có thể giúp cung cấp bộ lọc trong hộp thoại chọn tệp của HĐH. Ví dụ,

<!-- (IE 10+, Edge (EdgeHTML), Edge (Chromium), Chrome, Firefox 42+) -->
<input type="file" accept=".xls,.xlsx" />

nên cung cấp một cách để lọc các tệp khác ngoài .xls hoặc .xlsx. Mặc dù trang MDN cho inputphần tử luôn nói rằng nó hỗ trợ điều này, nhưng thật ngạc nhiên, điều này không hoạt động với tôi trong Firefox cho đến phiên bản 42. Điều này hoạt động trong IE 10+, Edge và Chrome.

Vì vậy, để hỗ trợ Firefox cũ hơn 42 cùng với IE 10+, Edge, Chrome và Opera, tôi đoán sẽ tốt hơn khi sử dụng danh sách các loại MIME được phân tách bằng dấu phẩy:

<!-- (IE 10+, Edge (EdgeHTML), Edge (Chromium), Chrome, Firefox) -->
<input type="file"
 accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel" /> 

Hành vi [ Edge (EdgeHTML): thả xuống bộ lọc loại tệp hiển thị các loại tệp được đề cập ở đây, nhưng không phải là mặc định trong danh sách thả xuống. Bộ lọc mặc định là All files (*).]

Bạn cũng có thể sử dụng dấu hoa thị theo kiểu MIME. Ví dụ:

<input type="file" accept="image/*" /> <!-- all image types --> 
<input type="file" accept="audio/*" /> <!-- all audio types --> 
<input type="file" accept="video/*" /> <!-- all video types --> 

W3C khuyến nghị các tác giả chỉ định cả loại MIME và phần mở rộng tương ứng trong acceptthuộc tính. Vì vậy, cách tiếp cận tốt nhất là:

<!-- Right approach: Use both file extensions and corresponding MIME-types. -->
<!-- (IE 10+, Edge (EdgeHTML), Edge (Chromium), Chrome, Firefox) -->
<input type="file"
 accept=".xls,.xlsx, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel" /> 

JSFiddle giống nhau: ở đây .

Tham khảo: Danh sách các loại MIME

QUAN TRỌNG: Sử dụng acceptthuộc tính chỉ cung cấp cách lọc trong các tệp thuộc loại quan tâm. Trình duyệt vẫn cho phép người dùng chọn các loại tệp. Các kiểm tra bổ sung (phía máy khách) nên được thực hiện (sử dụng JavaScript, một cách là như vậy ) và chắc chắn các loại tệp PHẢI được xác minh trên máy chủ , sử dụng kết hợp loại MIME bằng cả phần mở rộng tệp và chữ ký nhị phân của nó ( ASP .NET , PHP , Ruby , Java ). Bạn cũng có thể muốn tham khảo các bảng này cho các loại tệp và số ma thuật của chúng, để thực hiện xác minh phía máy chủ mạnh mẽ hơn.

Dưới đây là ba cách đọc tốt về tải lên tập tin và bảo mật.

EDIT: Có thể xác minh loại tệp bằng chữ ký nhị phân của nó cũng có thể được thực hiện ở phía máy khách bằng cách sử dụng JavaScript (thay vì chỉ nhìn vào phần mở rộng) bằng API tệp HTML5, nhưng vẫn phải xác minh tệp trên máy chủ, vì người dùng độc hại vẫn có thể tải lên các tệp bằng cách thực hiện một yêu cầu HTTP tùy chỉnh.


2
@Sandesire Tôi không nghĩ rằng bạn có thể hạn chế kích thước tệp trong HTML. Có thể sử dụng JavaScript, như bạn đề xuất.
Sachin Joseph

1
Theo kinh nghiệm cá nhân của tôi, đây có vẻ là một câu trả lời hay, một mình loại mime sẽ không hoạt động trên tất cả các trình duyệt.
Barshe Roussy

1
Ngẫu nhiên acceptvẫn không hoạt động trong Edge: stackoverflow.com/questions/31875617/ . Thêm chi tiết tại đây: wpdev.uservoice.com/forums/257854-microsoft-edge-developer/ từ
SharpC

1
Tôi muốn chúng tôi có một sự lựa chọn để loại trừ các tập tin, ví dụ exclude="exe". _ (ツ) _ /
Sagiv bg

1
Để làm rõ hơn hành vi của Edge (theo các thử nghiệm của tôi), nó sẽ thêm các bộ lọc khác nhau dựa trên những gì bạn chỉ định, nhưng a) nó không được đóng gói, vì vậy nó sẽ liệt kê mỗi tiện ích mở rộng dưới dạng một tùy chọn riêng biệt và b) nó sẽ luôn thêm một số xây dựng các tiện ích mở rộng như .html và c) như đã nêu, nó sẽ luôn được chọn trước (*). Điều này làm cho nó trở thành một mớ hỗn độn lớn và vô dụng trong hầu hết các trường hợp. Tôi đã bỏ phiếu trên liên kết uservoice, hãy hy vọng họ sớm muộn gì cũng nghe.
Arie

198

Có thuộc tính chấp nhận cho thẻ đầu vào. Tuy nhiên, nó không đáng tin cậy theo bất kỳ cách nào. Các trình duyệt rất có thể coi nó là một "gợi ý", nghĩa là người dùng cũng sẽ tùy thuộc vào trình quản lý tệp, có một lựa chọn trước chỉ hiển thị các loại mong muốn. Họ vẫn có thể chọn "tất cả các tệp" và tải lên bất kỳ tệp nào họ muốn.

Ví dụ:

<form>
    <input type="file" name="pic" id="pic" accept="image/gif, image/jpeg" />
</form>

Đọc thêm trong thông số HTML5

Hãy nhớ rằng nó chỉ được sử dụng như một "trợ giúp" cho người dùng để tìm đúng tệp. Mọi người dùng có thể gửi bất kỳ yêu cầu nào anh ấy / cô ấy muốn đến máy chủ của bạn. Bạn luôn phải xác nhận mọi thứ phía máy chủ.

Vì vậy, câu trả lời là: không bạn không thể hạn chế , nhưng bạn có thể đặt lựa chọn trước nhưng bạn không thể dựa vào nó.

Ngoài ra, bạn cũng có thể làm điều gì đó tương tự bằng cách kiểm tra tên tệp (giá trị của trường đầu vào) bằng JavaScript, nhưng điều này là vô nghĩa vì nó không bảo vệ và cũng không dễ dàng lựa chọn cho người dùng. Nó chỉ có khả năng lừa một quản trị trang web nghĩ rằng anh ấy / cô ấy được bảo vệ và mở một lỗ hổng bảo mật. Nó có thể gây khó khăn cho người dùng có phần mở rộng tệp thay thế (ví dụ jpeg thay vì jpg), chữ hoa hoặc không có phần mở rộng tệp nào (như thường thấy trên các hệ thống Linux).


3
để biết thêm thông tin, hãy xem stackoverflow.com/questions/181214/
Ấn

1
Mặc dù đúng là không thể ngăn người dùng chọn bất kỳ loại tệp nào, nhưng ngày nay bạn có thể tận dụng API tệp HTML5 và làm việc với tệp đã chọn để tải lên, trước khi nó thực sự được tải lên máy chủ, bao gồm cả việc phát hiện loại của nó, kích thước và nhiều hơn nữa. Hãy thử một lần. Nó rất dễ sử dụng, nhưng rất mạnh mẽ và hữu ích.
TheCuBeMan

96

Bạn có thể sử dụng changesự kiện để theo dõi những gì người dùng chọn và thông báo cho họ tại thời điểm đó rằng tệp không được chấp nhận. Nó không giới hạn danh sách thực tế của các tệp được hiển thị, nhưng nó là thứ gần nhất bạn có thể làm phía máy khách, bên cạnh acceptthuộc tính được hỗ trợ kém .

var file = document.getElementById('someId');

file.onchange = function(e) {
  var ext = this.value.match(/\.([^\.]+)$/)[1];
  switch (ext) {
    case 'jpg':
    case 'bmp':
    case 'png':
    case 'tif':
      alert('Allowed');
      break;
    default:
      alert('Not allowed');
      this.value = '';
  }
};
<input type="file" id="someId" />

Câu đố


11
@joe, đây là một ví dụ ... nó có thể mở rộng đến bất kỳ tiện ích mở rộng nào bạn muốn cho phép.
Gabriele Petrioli

Vâng bạn có thể. nhưng bạn KHÔNG! và maby ai đó đã sao chép nó rồi! và những gì về các tập tin với loại mime chính xác nhưng không có phần mở rộng?
Surrican

49
@Joe .. tốt .. tôi cố gắng cung cấp hướng và logic âm thanh. Không thực hiện đầy đủ các giải pháp cho mọi trường hợp. Tôi tin tưởng người xem sử dụng lẽ thường khi sao chép / dán mã từ trang web;)
Gabriele Petrioli

7
Làm thế nào về "Một số.File.jpg"? Có lẽ dòng regex đó cần đọc: var ext = this.value.match (/ \. ([^.] +) $ /) [1];
Jon Kloske

Vấn đề với cách tiếp cận này là một cái gì đó về mặt kỹ thuật vẫn có thể là một jpeg ngay cả khi nó không kết thúc với phần mở rộng đó. Tiện ích mở rộng! == loại mime
Matt Fletcher

46

Vâng, bạn đúng. Không thể với HTML. Người dùng sẽ có thể chọn bất kỳ tập tin nào anh ấy / cô ấy muốn.

Bạn có thể viết một đoạn mã JavaScript để tránh gửi tệp dựa trên phần mở rộng của nó. Nhưng hãy nhớ rằng điều này không có nghĩa là sẽ ngăn người dùng độc hại gửi bất kỳ tệp nào mà anh ấy / cô ấy thực sự muốn.

Cái gì đó như:

function beforeSubmit()
{
    var fname = document.getElementById("ifile").value;
    // check if fname has the desired extension
    if (fname hasDesiredExtension) {
        return true;
    } else {
        return false;
    }
}

Mã HTML:

<form method="post" onsubmit="return beforeSubmit();">
    <input type="file" id="ifile" name="ifile"/>
</form>

3
có một thuộc tính html hoàn toàn hợp lệ cho điều đó là có thể. nó chỉ không được các trình duyệt tôn trọng, nhưng đó là một vấn đề tiêu chuẩn hóa. cũng như mọi nội dung được xử lý phía máy khách trong đánh dấu không được bảo vệ không thể hạn chế bất cứ điều gì tập lệnh java không có giải pháp.
Surrican

2
Điểm rất tốt. Tôi sẽ thêm một trình kiểm tra PHP thứ hai chỉ trong trường hợp. Không thể quá cẩn thận!
Bojangles

2
Chà, cũng chẳng hại gì nếu tôi cũng đang sử dụng tập lệnh xác thực PHP, vì vậy tôi sẽ sử dụng cả hai.
Bojangles

17
@Joe: đừng nói rằng câu trả lời của tôi thật tệ! :-) Dù sao, nó không phải là một giải pháp hoàn hảo. Như tôi đã nói lúc đầu: "không thể" làm điều OP muốn. Nhưng bạn có thể có một số mức độ trợ giúp cho người dùng nếu bạn chỉ cho phép anh ấy / cô ấy chọn các tệp có phần mở rộng nhất định. REAL tập tin loại xác nhận phải được thực hiện phía máy chủ .
Pablo Santa Cruz

11
@JoeHopfgartner: Anh bạn, quá khắc nghiệt đối với Pablo ở đây. xác thực máy khách được thực hiện ở hàng tấn địa điểm và mặc dù không thể đánh lừa được (nên luôn luôn có [/ b] bao gồm xác thực máy chủ), nó có thể tiết kiệm cho người dùng khá nhiều thời gian (không phải đăng lại để kiểm tra tiện ích mở rộng ngu ngốc, v.v.). Mặc dù kịch bản do Pablo đưa ra không hoàn hảo, nhưng nó chỉ nhằm mục đích là một ví dụ về cách giải quyết vấn đề này ... Có lẽ bạn nên gửi email cho các nhân viên công nghệ tại Microsoft và yêu cầu họ xóa xác thực Cl Clientide khỏi trình xác thực ASP.NET của họ kể từ đó tất cả đều là rác rưởi đối với bạn ...
Nathan

18

Về mặt kỹ thuật, bạn có thể chỉ định acceptthuộc tính (thay thế trong html5 ) trên inputphần tử, nhưng nó không được hỗ trợ đúng cách.


Hỗ trợ trình duyệt W3Schools thất bại! Thật là xấu hổ. Đây cũng là một vấn đề bảo mật - mọi người có thể hack mã phía máy khách và tải lên bất cứ thứ gì họ muốn.
Bojangles

5
Đúng, tốt nhất là không sử dụng điều này để bảo mật, nhưng nó chắc chắn giúp ích cho khả năng sử dụng trên các trình duyệt hỗ trợ nó. Người dùng chỉ được hiển thị các tệp mà trang web cho phép (không phải tất cả các rác khác mà họ có thể có trong cùng một thư mục) và họ không phải trải qua toàn bộ quá trình tải lên để được thông báo lỗi, họ sẽ biết ngay. Coders nên sử dụng cái này.
Simon East

10

Sử dụng inputthẻ với acceptthuộc tính

<input type="file" name="my-image" id="image" accept="image/gif, image/jpeg, image/png" />

Bấm vào đây để xem bảng tương thích trình duyệt mới nhất

Bản demo trực tiếp tại đây

Để chỉ chọn các tệp hình ảnh, bạn có thể sử dụng accept="image/*"

<input type="file" name="my-image" id="image" accept="image/*" />

Bản demo trực tiếp tại đây

Chỉ gif, jpg và png sẽ được hiển thị, lấy màn hình từ Chrome phiên bản 44 Chỉ gif, jpg và png sẽ được hiển thị, lấy màn hình từ Chrome phiên bản 44


Cảm ơn! Trong Chrome trên Win10, nếu tôi sử dụng accept="image/*", nó sẽ ghi "Tệp hình ảnh" thay vì "Tệp tùy chỉnh" trong trình chọn tệp, rất phù hợp với người dùng cuối.
Teddy

Nhưng người dùng có thể thay đổi nó và tải lên tệp tiện ích mở rộng khác
Prashant Prajapati

@PrashantPrajapati Vâng, đó là cách trình duyệt được tạo, nên có xác nhận tương ứng trong máy chủ. Chức năng của trình duyệt chỉ dành cho trải nghiệm người dùng tốt hơn.
kiranvj

9

Tôi biết điều này là một chút muộn.

function Validatebodypanelbumper(theForm)
{
   var regexp;
   var extension =     theForm.FileUpload.value.substr(theForm.FileUpload1.value.lastIndexOf('.'));
   if ((extension.toLowerCase() != ".gif") &&
       (extension.toLowerCase() != ".jpg") &&
       (extension != ""))
   {
      alert("The \"FileUpload\" field contains an unapproved filename.");
      theForm.FileUpload1.focus();
      return false;
   }
   return true;
}

5

Bạn thực sự có thể làm điều đó với javascript nhưng hãy nhớ js là phía máy khách, vì vậy bạn thực sự sẽ là "cảnh báo người dùng" loại tệp nào họ có thể tải lên, nếu bạn muốn TRÁNH (hạn chế hoặc giới hạn như bạn đã nói) một số loại tệp bạn PHẢI làm nó phía máy chủ.

Nhìn vào tut cơ bản này nếu bạn muốn bắt đầu với xác nhận phía máy chủ. Đối với toàn bộ hướng dẫn truy cập trang này .

Chúc may mắn!


4

Như đã đề cập trong các câu trả lời trước, chúng tôi không thể hạn chế người dùng chọn các tệp chỉ cho các định dạng tệp đã cho. Nhưng nó thực sự tiện dụng khi sử dụng thẻ chấp nhận trên thuộc tính tệp trong html.

Để xác thực, chúng tôi phải làm điều đó ở phía máy chủ. Chúng tôi cũng có thể làm điều đó ở phía khách hàng trong js nhưng nó không phải là một giải pháp hoàn hảo. Chúng tôi phải xác nhận ở phía máy chủ.

Đối với những yêu cầu này, tôi thực sự thích struts2 khung phát triển ứng dụng web Java. Với tính năng tải lên tệp tích hợp, tải tệp lên các ứng dụng web dựa trên struts2 là một miếng bánh. Chỉ cần đề cập đến các định dạng tệp mà chúng tôi muốn chấp nhận trong ứng dụng của chúng tôi và tất cả phần còn lại được chăm sóc bởi chính lõi của khung. Bạn có thể kiểm tra nó tại trang web chính thức của struts.


3

Tôi có thể đề nghị như sau:

  • Nếu bạn phải làm cho người dùng chọn bất kỳ tệp hình ảnh nào theo mặc định, hãy sử dụng accept = "image / *"

    <input type="file" accept="image/*" />

  • nếu bạn muốn giới hạn các loại hình ảnh cụ thể thì hãy sử dụng accept = "image / bmp, image / jpeg, image / png"

    <input type="file" accept="image/bmp, image/jpeg, image/png" />

  • nếu bạn muốn giới hạn các loại cụ thể thì hãy sử dụng accept = ". bmp, .doc, .pdf"

    <input type="file" accept=".bmp, .doc, .pdf" />

  • Bạn không thể hạn chế người dùng thay đổi trình quay tệp thành tất cả các tệp, vì vậy luôn xác thực loại tệp trong tập lệnh và máy chủ


1
Đây là những gì tôi đang tìm kiếm: accept = ". Bmp" Hoạt động tốt trên chrome.
MichaelRom
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.