Limitare il formato del file quando si utilizza <input type = “file”>?


667

Vorrei limitare il tipo di file che può essere scelto dal selettore file del sistema operativo nativo quando l'utente fa clic sul pulsante Sfoglia <input type="file">nell'elemento in HTML. Ho la sensazione che è impossibile, ma mi piacerebbe sapere se v'è una soluzione. Mi piacerebbe mantenere esclusivamente HTML e JavaScript; nessun flash per favore.


1
È facilmente possibile con PHP, ma non so se puoi usarlo, quindi non pubblicherò il codice.
Latox,

2
Posso, ma ho una soluzione che funziona con JavaScript: rimuove il fastidio di caricare un file e ottenere il "File errato!" errore.
Bojangles,

Vedi anche la domanda più recente: stackoverflow.com/questions/181214/…
Christophe Roussy,

Una cosa da notare è che sebbene non sia ottimo per la convalida, accetta limiterà i file visibili a quelli accettati mentre l'utente li sta navigando (almeno in alcuni browser ...). Quindi questa è più una funzionalità di ergonomia dell'interfaccia utente che una di convalida.
Christophe Roussy,

Risposte:


1119

A rigor di termini, la risposta è no . Uno sviluppatore non può impedire a un utente di caricare file di qualsiasi tipo o estensione.

Tuttavia, l' attributo accetta di <input type = "file">può aiutare a fornire un filtro nella finestra di dialogo di selezione file del sistema operativo. Per esempio,

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

dovrebbe fornire un modo per filtrare file diversi da .xls o .xlsx. Sebbene la pagina MDN per inputelement abbia sempre detto che supporta questo, con mia sorpresa, questo non ha funzionato per me in Firefox fino alla versione 42. Funziona in IE 10+, Edge e Chrome.

Quindi, per supportare Firefox più vecchio di 42 insieme a IE 10+, Edge, Chrome e Opera, immagino sia meglio usare un elenco separato da virgole di tipi MIME:

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

Comportamento [ Edge (EdgeHTML): il menu a discesa del filtro del tipo di file mostra i tipi di file menzionati qui, ma non è il valore predefinito nel menu a discesa. Il filtro predefinito è All files (*).]

Puoi anche usare gli asterischi nei tipi MIME. Per esempio:

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

Il W3C raccomanda agli autori di specificare sia i tipi MIME che le estensioni corrispondenti acceptnell'attributo. Quindi, l' approccio migliore è:

<!-- 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 dello stesso: qui .

Riferimento: elenco di tipi MIME

IMPORTANTE: l' utilizzo acceptdell'attributo fornisce solo un modo per filtrare i file di tipi di interesse. I browser consentono ancora agli utenti di scegliere file di qualsiasi tipo. Dovrebbero essere effettuati controlli aggiuntivi (lato client) (usando JavaScript, un modo sarebbe questo ), e sicuramente i tipi di file DEVONO essere verificati sul server , usando una combinazione di tipo MIME usando sia l'estensione del file che la sua firma binaria ( ASP .NET , PHP , Ruby , Java ). Potresti anche fare riferimento a queste tabelle per i tipi di file e i loro numeri magici, per eseguire una verifica lato server più solida.

Ecco tre buone letture su upload di file e sicurezza.

EDIT: forse la verifica del tipo di file usando la sua firma binaria può essere fatta anche sul lato client usando JavaScript (piuttosto che semplicemente guardando l'estensione) usando l'API File HTML5, ma comunque, il file deve essere verificato sul server, perché un utente malintenzionato sarà comunque in grado di caricare file facendo una richiesta HTTP personalizzata.


2
@Sandesire Non penso che puoi limitare le dimensioni dei file in HTML. È possibile utilizzare JavaScript, come hai suggerito.
Sachin Joseph,

1
Dalla mia esperienza personale questa sembra una buona risposta, il tipo mime da solo non funzionerà su tutti i browser.
Christophe Roussy,

1
Per inciso accept, non funziona ancora in Edge: stackoverflow.com/questions/31875617/… . Maggiori dettagli qui: wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
SharpC

1
Vorrei che avessimo avuto la possibilità di escludere anche i file, per esempio exclude="exe". ¯_ (ツ) _ / ¯
Sagiv bg

1
Per chiarire ulteriormente il comportamento di Edge (secondo i miei test), aggiungerà diversi filtri in base a ciò che specifichi, ma a) non è raggruppato, quindi elencherà ogni estensione come un'opzione separata eb) aggiungerà sempre alcuni in- crea estensioni come .html ec) come già detto, preselezionerà sempre (*). Il che lo rende un gran casino e inutile nella maggior parte dei casi. Ho votato sul link uservoice, speriamo che prima o poi ascoltino.
Arie,

198

C'è l'attributo accetta per il tag di input. Tuttavia, non è affidabile in alcun modo. Molto probabilmente i browser lo trattano come un "suggerimento", il che significa che l'utente, a seconda del gestore dei file, avrà una preselezione che visualizza solo i tipi desiderati. Possono comunque scegliere "tutti i file" e caricare tutti i file desiderati.

Per esempio:

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

Leggi di più in specifiche HTML5

Tieni presente che deve essere utilizzato solo come "aiuto" affinché l'utente possa trovare i file giusti. Ogni utente può inviare qualsiasi richiesta desidera al tuo server. Devi sempre convalidare tutto sul lato server.

Quindi la risposta è: no non puoi limitare , ma puoi impostare una preselezione ma tu puoi fare affidamento su di essa.

In alternativa o in aggiunta puoi fare qualcosa di simile controllando il nome del file (valore del campo di input) con JavaScript, ma non ha senso perché non fornisce protezione e non facilita la selezione per l'utente. Potenzialmente induce un webmaster a pensare che sia protetto e apre una falla nella sicurezza. Può essere una seccatura per gli utenti che hanno estensioni di file alternative (ad esempio jpeg anziché jpg), maiuscole o nessuna estensione di file (come è comune sui sistemi Linux).


3
Per ulteriori informazioni, vedere stackoverflow.com/questions/181214/...
Martin Meeser

1
Anche se è vero che è impossibile impedire all'utente di selezionare QUALSIASI tipo di file, in questi giorni è possibile sfruttare l'API del file HTML5 e lavorare con il file selezionato per il caricamento, prima che venga effettivamente caricato sul server, incluso il rilevamento il suo tipo, dimensioni e altro ancora. Provaci. È molto facile da usare, ma molto potente e utile.
TheCuBeMan

96

È possibile utilizzare l' changeevento per monitorare ciò che l'utente seleziona e avvisare a quel punto che il file non è accettabile. Non limita l'elenco effettivo dei file visualizzati, ma è il più vicino che puoi fare sul lato client, oltre acceptall'attributo scarsamente supportato .

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, è un esempio ... può estendersi a qualsiasi estensione che si desidera consentire.
Gabriele Petrioli,

sì, puoi. ma NON lo hai fatto! e maby qualcuno l'ha già copiato! e che dire dei file con il tipo MIME corretto ma senza estensione?
The Surrican,

49
@Joe .. beh .. provo a fornire una direzione e una logica del suono. Soluzioni non completamente implementate per ogni caso. Confido che gli spettatori utilizzino il buon senso quando copiano / incollano il codice dal web;)
Gabriele Petrioli,

7
Che ne dici di "Some.File.jpg"? Forse quella riga regex deve essere letta: var ext = this.value.match (/ \. ([^.] +) $ /) [1];
Jon Kloske,

Il problema con questo approccio è che qualcosa potrebbe tecnicamente essere un jpeg anche se non si esaurisce con tale estensione. Estensioni! == tipi mime
Matt Fletcher

46

Si hai ragione. È impossibile con HTML. L'utente sarà in grado di scegliere qualsiasi file desidera.

È possibile scrivere un pezzo di codice JavaScript per evitare di inviare un file in base alla sua estensione. Ma tieni presente che ciò non impedirà in alcun modo a un utente malintenzionato di inviare qualsiasi file che desidera davvero.

Qualcosa di simile a:

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

Codice HTML:

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

3
esiste un attributo html completamente valido per questo, quindi è possibile. non è rispettato dai browser, ma è un problema di standardizzazione. così come qualsiasi cosa gestita sul lato client nel markup non protetto non può limitare nulla, lo script java non è una soluzione.
The Surrican,

2
Ottimo punto Aggiungerò un secondo correttore PHP per ogni evenienza. Non posso stare troppo attento!
Bojangles,

2
Bene, non fa male se sto usando anche uno script di validazione PHP, quindi userò entrambi.
Bojangles,

17
@Joe: smetti di dire che la mia risposta fa schifo! :-) Comunque, non è una soluzione perfetta. Come ho detto all'inizio: "è impossibile" fare ciò che vuole OP. Ma puoi avere un certo grado di aiuto per l'utente se gli lasci solo scegliere i file con determinate estensioni. La convalida del tipo di file REAL deve essere eseguita sul lato server .
Pablo Santa Cruz,

11
@JoeHopfgartner: Amico, stai diventando troppo duro per Pablo qui. la convalida del cliente viene eseguita in molti posti e sebbene non sia infallibile (dovrebbe essere sempre inclusa la [b] [/ b] convalida del lato server) può far risparmiare un po 'di tempo all'utente (nessun postback per uno stupido controllo delle estensioni ecc.). Sebbene lo script fornito da Pablo non sia perfetto, è semplicemente inteso come un esempio di come affrontare questo problema ... Forse dovresti inviare un'e-mail ai tecnici di Microsoft e chiedere loro di rimuovere la convalida Clientside dai loro validatori ASP.NET da è tutta spazzatura per te ...
Nathan,

18

Tecnicamente puoi specificare l' acceptattributo (alternativa in html5 ) inputsull'elemento, ma non è supportato correttamente.


Il supporto del browser W3Schools fallisce! È davvero un peccato. È anche un problema di sicurezza: le persone possono hackerare il codice lato client passato e caricare ciò che vogliono.
Bojangles,

5
È vero, è meglio non usarlo per sicurezza, ma sicuramente aiuta l'usabilità sui browser che lo supportano. Agli utenti vengono mostrati solo i file consentiti dal sito (non tutti gli altri file spazzatura che potrebbero avere nella stessa cartella) e non devono passare attraverso l'intero processo di caricamento per ricevere un errore, lo sapranno immediatamente. I programmatori dovrebbero usare questo.
Simon East,

10

Usa inputtag con acceptattributo

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

Fai clic qui per l'ultima tabella di compatibilità del browser

Demo live qui

Per selezionare solo i file di immagine, è possibile utilizzare questo accept="image/*"

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

Demo live qui

Verranno visualizzati solo gif, jpg e png, schermata catturata dalla versione 44 di Chrome Verranno visualizzati solo gif, jpg e png, schermata catturata dalla versione 44 di Chrome


Grazie! In Chrome su Win10, se uso accept="image/*", dice "File immagine" invece di "File personalizzati" nel selettore file, il che è utile per l'utente finale.
Teddy

Ma l'utente può cambiarlo e caricare l'altro file di estensione
Prashant Prajapati il

@PrashantPrajapati Sì, ecco come sono fatti i browser, dovrebbe esserci una corrispondente validazione nel server. La funzionalità del browser è solo per una migliore esperienza utente.
Kiranvj,

9

So che è un po 'tardi.

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

In realtà potresti farlo con javascript ma ricorda che js è lato client, quindi in realtà "avvertiresti gli utenti" che tipo di file possono caricare, se vuoi EVITARE (limitare o limitare come hai detto) un determinato tipo di file DEVI fallo sul lato server.

Guarda questo tutorial di base se desideri iniziare con la convalida lato server. Per l'intero tutorial visita questa pagina .

In bocca al lupo!


4

Come menzionato nelle risposte precedenti, non possiamo limitare l'utente a selezionare i file solo per determinati formati di file. Ma è davvero utile usare il tag accetta sull'attributo file in html.

Per quanto riguarda la convalida, dobbiamo farlo sul lato server. Possiamo anche farlo sul lato client in js ma non è una soluzione infallibile. Dobbiamo convalidare sul lato server.

Per questi requisiti preferisco davvero il framework di sviluppo di applicazioni web Java struts2. Con la sua funzione di caricamento file integrata, caricare file su app Web basate su struts2 è un gioco da ragazzi. Basta menzionare i formati di file che vorremmo accettare nella nostra applicazione e tutto il resto è curato dal nucleo del framework stesso. Puoi dare un'occhiata al sito ufficiale di struts.


3

Posso suggerire quanto segue:

  • Se devi fare in modo che l'utente selezioni uno qualsiasi dei file immagine per impostazione predefinita, l'uso accetta = "image / *"

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

  • se si desidera limitare a tipi di immagine specifici, utilizzare accept = "image / bmp, image / jpeg, image / png"

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

  • se si desidera limitare a tipi specifici, utilizzare accept = ". bmp, .doc, .pdf"

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

  • Non è possibile limitare l'utente a modificare il file filer in tutti i file, quindi convalidare sempre il tipo di file in script e server


1
Questo era quello che stavo cercando: accept = ". Bmp" Funziona bene su Chrome.
MichaelRom
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.