Обмежити формат файлу при використанні <input type = "file">?


667

Я хотів би обмежити тип файлу, який можна вибрати з вибору власного файлу ОС, коли користувач натискає кнопку Огляд в <input type="file">елементі HTML. У мене є відчуття, що це неможливо, але я хотів би знати, чи є рішення. Я хотів би зберегти виключно HTML та JavaScript; ні Flash, будь ласка.


1
Це легко можливо за допомогою PHP, але я не знаю, чи можете ви використовувати це, щоб я не публікував код.
Latox

2
Я можу, але у мене є рішення, що працює з JavaScript - воно знімає роздратування щодо завантаження файлу, а потім отримує "Неправильний файл!" помилка.
Bojangles

Дивіться також останнє запитання: stackoverflow.com/questions/181214/…
Крістоф Руссі

Варто зазначити, що, хоча це не чудово для перевірки, функція accept обмежує видимі файли прийнятими, поки користувач переглядає їх (принаймні в деяких браузерах ...). Отже, це швидше функція ергономіки інтерфейсу, ніж перевірка.
Крістоф Руссі

Відповіді:


1119

Строго кажучи, відповідь - ні . Розробник не може перешкодити користувачеві завантажувати файли будь-якого типу або розширення.

Але все ж, атрибут accept<input type = "file"> може допомогти забезпечити фільтр у діалоговому вікні вибору файлів ОС. Наприклад,

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

має забезпечити спосіб фільтрації інших файлів, ніж .xls або .xlsx. Хоча сторінка MDN для inputелемента завжди говорила, що це підтримує, на моє здивування, це не працювало для мене у Firefox до версії 42. Це працює в IE 10+, Edge та Chrome.

Отже, для підтримки Firefox старше 42 років, а також IE 10+, Edge, Chrome та Opera, я думаю, що краще використовувати список розділених комами типів MIME:

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

Поведінка [ Edge (EdgeHTML): випадаючий фільтр типу файлу показує типи файлів, згадані тут, але не є типовим у спадному меню. Фільтр за замовчуванням All files (*).]

Ви також можете використовувати зірочки в MIME-типах. Наприклад:

<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 рекомендує авторам вказати як acceptатрибут MIME, так і відповідні розширення . Отже, найкращий підхід:

<!-- 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 того ж: тут .

Довідка: Список типів MIME

ВАЖЛИВО: Використання acceptатрибуту надає лише спосіб фільтрації у файлах, що представляють інтерес. Браузери все ще дозволяють користувачам вибирати файли будь-якого типу. Додатково ( на стороні клієнта) перевірки повинні бути зроблені ( з використанням JavaScript, один з способів було б це ), і безумовно типи файлів повинні бути перевірені на сервері , використовуючи комбінацію MIME-типу з використанням як розширення файлу і його двійкову підпис ( ASP .NET , PHP , Ruby , Java ). Ви також можете звернутися до цих таблиць щодо типів файлів та їх магічних чисел, щоб виконати більш надійну перевірку на стороні сервера.

Ось три хороших читання щодо завантаження файлів та безпеки.

EDIT: Можливо, перевірку типу файлів за допомогою його двійкового підпису можна виконати і на стороні клієнта за допомогою JavaScript (а не просто, дивлячись на розширення) за допомогою API File5 HTML5, але все-таки файл повинен бути перевірений на сервері, оскільки зловмисний користувач як і раніше зможе завантажувати файли, зробивши спеціальний HTTP-запит.


2
@Sandesire Я не думаю, що ви можете обмежити розміри файлів у HTML. Можна використовувати JavaScript, як ви запропонували.
Сачин Йосиф

1
З мого особистого досвіду це виглядає як хороша відповідь, тільки тип міми не працюватиме у всіх браузерах.
Крістоф Руссі

1
До речі до acceptсих пір не працює в Edge: stackoverflow.com/questions/31875617 / ... . Більше деталей тут: wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
SharpC

1
Я б хотіла, щоб у нас був вибір також виключити файли, наприклад exclude="exe". _ (ツ) _ / ¯
Sagiv BG

1
Щоб додатково уточнити поведінку Edge (згідно з моїми тестами), він додасть різні фільтри залежно від того, що ви вказали, але а) це не в комплекті, тому воно буде перераховувати кожне розширення як окремий варіант; б) воно завжди додаватиме деякі вбудовані- будуйте розширення, такі як .html та c), як уже було зазначено, він завжди буде попередньо обраний (*). Що робить це великим безладом і марним у більшості випадків. Я проголосував за посиланням для користувачів, сподіваємось, що вони рано чи пізно прослухають.
Ар'є

198

Існує атрибут accept для тегу введення. Однак це ні в якому разі не є надійним. Браузери, швидше за все, трактують це як "пропозицію", тобто користувач, залежно від файлового менеджера, також має попередній вибір, який відображатиме лише потрібні типи. Вони все ще можуть вибрати "всі файли" та завантажити будь-який потрібний файл.

Наприклад:

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

Детальніше читайте в специфікації HTML5

Майте на увазі, що користувач може використовуватись лише як "допомога" для пошуку потрібних файлів. Кожен користувач може надіслати будь-який запит, який він бажає, на ваш сервер. Ви завжди повинні перевірити все на сервері.

Отже, відповідь: ні, ви не можете обмежуватись , але ви можете встановити попередній вибір, але ви не можете покластися на нього.

Альтернативно або додатково ви можете зробити щось подібне, перевіривши ім'я файлу (значення поля введення) за допомогою JavaScript, але це нісенітниця, оскільки він не забезпечує захисту, а також не полегшує вибір для користувача. Це лише потенційно обманює веб-майстра думати, що він / вона захищений, і відкриває отвір у захисті. Користувачам, які мають альтернативні розширення файлів (наприклад, jpeg замість jpg), великі регістри або взагалі відсутні розширення файлів (як це часто в системах Linux), це може бути болем у попці.


3
Для отримання додаткової інформації див stackoverflow.com/questions/181214 / ...
Martin Meeser

1
Хоча це правда, що неможливо унеможливити вибір користувача будь-якого типу файлів у кінцевому підсумку, в ці дні ви можете скористатися API-файлом HTML5 та працювати з обраним файлом для завантаження, перш ніж він буде фактично завантажений на сервер, включаючи виявлення її тип, розмір та інше. Спробувати. Він дуже простий у використанні, але при цьому дуже потужний і корисний.
TheCuBeMan

96

Ви можете використовувати changeподію для того, щоб стежити за тим, що вибирає користувач, і повідомляти їх про те, що файл неприйнятний. Він не обмежує фактичний список файлів, що відображаються, але це найближчий список клієнтів, окрім погано підтримуваного acceptатрибута.

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" />

JSFiddle


11
@joe, це приклад ... він може поширюватися на всі розширення, які ви хочете дозволити.
Габріеле Петріолі

так, можна. але ти НЕ МАЄТЬ! і мабі хтось вже скопіював це! а що з файлами правильного типу mime, але без розширення?
The Surrican

49
@Joe .. ну .. я намагаюся надати напрямок і здорову логіку. Не повністю реалізовані рішення для кожного випадку. Я довіряю глядачам використовувати здоровий глузд під час копіювання / вставлення коду з Інтернету;)
Габріеле Петріолі

7
Як щодо "Some.File.jpg"? Можливо, в цьому рядку регулярних виразів потрібно прочитати: var ext = this.value.match (/ \. ([^.] +) $ /) [1];
Джон Клоске

Проблема такого підходу полягає в тому, що щось технічно все-таки може бути jpeg, навіть якщо це не закінчується цим розширенням. Розширення! == mime
Метт Флетчер

46

Так, ти правий. З HTML це неможливо. Користувач зможе вибрати будь-який файл, який він / вона захоче.

Ви можете написати фрагмент коду JavaScript, щоб не надсилати файл на основі його розширення. Але майте на увазі, що це жодним чином не завадить зловмисникові надсилати будь-який файл, який він дійсно хоче.

Щось на зразок:

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

HTML-код:

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

3
для цього є повністю дійсний атрибут html, тому це можливо. браузери просто не дотримуються, але це проблема стандартизації. а також будь-яка сторона, що обробляється клієнтом, при незахищеній розмітці нічого не може обмежувати, сценарій Java не є рішенням.
The Surrican

2
Дуже хороший момент. Я додам другу перевірку PHP про всяк випадок. Не може бути занадто обережним!
Bojangles

2
Ну, це не шкодить, якщо я теж використовую сценарій перевірки PHP, тому я буду використовувати обидва.
Bojangles

17
@Joe: перестань говорити, що моя відповідь відстійна! :-) У всякому разі, це не ідеальне рішення. Як я вже говорив на початку: "неможливо" робити те, що хоче ОП. Але ви можете надати певну допомогу користувачеві, якщо ви лише дозволите йому вибрати файли з певними розширеннями. ПОВЕРНЕННЯ перевірка типу файлів повинна бути виконана на стороні сервера .
Пабло Санта-Крус

11
@JoeHopfgartner: Чувак, ти тут надто суворий за Пабло. Перевірка клієнтів проводиться в тоннах місць, і хоча це не є надійною (завжди має бути [b] завжди [/ b] включена валідація на сервері), це може заощадити користувача досить довгий час (відсутність поштових зворотів для дурної перевірки розширення тощо). Хоча сценарій, наданий Pablo, не є ідеальним, він просто призначений бути прикладом того, як вирішити цю проблему ... Можливо, ви повинні надіслати електронні повідомлення технічним хлопцям у Microsoft і попросити їх видалити перевірку клієнтів з їх валідаторів ASP.NET, оскільки це все просто сміття для вас ...
Натан

18

Технічно ви можете вказати acceptатрибут (альтернативу в html5 ) для inputелемента, але він належним чином не підтримується.


Не вдалося підтримати браузер W3Schools! Це справді соромно. Це також викликає занепокоєння щодо безпеки - люди можуть зламати попередній код клієнта та завантажувати все, що хочуть.
Bojangles

5
Щоправда, найкраще не використовувати це для безпеки, але це безумовно допомагає зручності використання у веб-переглядачах, які його підтримують. Користувачам показуються лише ті файли, які дозволяє сайт (не всі інші непотрібні файли, які вони можуть мати в одній папці), і їм не потрібно проходити весь процес завантаження, щоб отримати помилку, вони дізнаються відразу. Кодери повинні використовувати це.
Саймон Схід

10

Використовуйте inputтег з acceptатрибутом

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

Клацніть тут, щоб отримати останню таблицю сумісності браузера

Тут демонструють демо-версію

Щоб вибрати лише файли зображень, ви можете скористатися цим accept="image/*"

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

Тут демонструють демо-версію

Буде показано лише gif, jpg та png, захоплення екрана з версії 44 Chrome Буде показано лише gif, jpg та png, захоплення екрана з версії 44 Chrome


Дякую! У Chrome на Win10, якщо я використовую accept="image/*", він вибирає "Файли зображень" замість "Спеціальні файли" у виборі файлів, що приємно для кінцевого користувача.
Тедді

Але користувач може змінити його та завантажити інший файл розширення
Prashant Prajapati

@PrashantPrajapati Так, для того, як робляться браузери, має бути відповідна перевірка сервера. Функціональність браузера призначена лише для кращого користувацького досвіду.
kiranvj

9

Я знаю, це трохи пізно.

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

Ви насправді можете це робити за допомогою JavaScript, але пам’ятайте, що js є клієнтом, тому ви насправді будете "попереджати користувачів", який тип файлів вони можуть завантажувати, якщо ви хочете ОБМЕЖИТИ (обмежити або обмежити, як ви вже сказали) певний тип файлів, які ВАМ ПОВИНЕН зробіть це на стороні сервера.

Подивіться на цей основний документ, якщо ви хочете почати з перевірки на стороні сервера. Для всього підручника відвідайте цю сторінку .

Удачі!


4

Як було сказано в попередніх відповідях, ми не можемо обмежити користувача вибирати файли лише для заданих форматів файлів. Але дуже зручно використовувати атрибут accept на атрибут файлу в html.

Що стосується перевірки, ми повинні це зробити на стороні сервера. Ми також можемо це зробити на стороні клієнта в js, але це не є надійним рішенням. Ми повинні перевірити на стороні сервера.

Для цих вимог я дуже віддаю перевагу структурі розробки веб-додатків struts2 Java. Завдяки вбудованій функції завантаження файлів завантаження файлів у веб-додатки на основі struts2 - це торт. Просто згадайте формати файлів, які ми хотіли б прийняти у своїй програмі, а про все інше піклується ядро ​​самої основи. Ви можете перевірити це на офіційному сайті struts.


3

Я можу запропонувати наступне:

  • Якщо вам потрібно змусити користувача обрати будь-який із файлів зображень за замовчуванням, використовуйте accept = "image / *"

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

  • якщо ви хочете обмежитися певними типами зображень, тоді використовуйте accept = "image / bmp, image / jpeg, image / png"

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

  • якщо ви хочете обмежитися певними типами, тоді використовуйте accept = ". bmp, .doc, .pdf"

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

  • Ви не можете обмежити користувача змінювати файловий файл на всі файли, тому завжди перевіряйте тип файлу в скрипті та на сервері


1
Це те, що я шукав: accept = ". Bmp" Чудово працює на хромі.
MichaelRom
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.