Gli elementi <input>
con type="file"
danno all'utente la possibilità di scegliere uno o più file dalla memoria del proprio dispositivo. Una volta scelti, i file possono essere caricati su un server usando l'invio del modulo, oppure manipolati usando del codice JavaScript e l'API File
Value | Una DOMString che rappresenta il percorso del file selezionato. |
Eventi | change e input |
Attributi comuni supportati | required |
Attributi aggiuntivi | accept , capture , files , multiple |
Attributi IDL | files e value |
Interfaccia DOM | |
Proprietà | |
Metodi | select() |
Value
L'attributo value
di un file
contiene una DOMString
che rappresenta il percorso del file selezionato. Se l'utente seleziona più di un file, l'attributo value
rappresenta il primo file nella lista di quelli selezionati. Gli altri file possono essere identificati usando la proprietà HTMLInputElement.files
.
- Se vengono selezionati più file, la stringa rappresenta il primo. JavaScript può accedere agli atri file attraverso la proprietà
files
dell'elementoinput
- Se non è stato ancora selezionato nessun file, la stringa è
""
(vuota) - Alla stringa viene aggiunto il prefisso
C:\fakepath\
, per impedire a software malevolo di intuire la struttura del filesystem dell'utente.
Attributi aggiuntivi
In aggiunta agli attributi comuni a tutti gli elementi <input>
, gli input
di tipo file
supportano anche i seguenti:
Attributo | Descrizone |
---|---|
accept |
Uno o più Identificatori univoci del tipo di file che descrivono i tipi di file ammessi |
capture |
La sorgente da utilizzare per catturare immagini o dati video |
files |
Una FileList che elenca i file scelti |
multiple |
Un valore booleano che, se presente, indica che l'utente può selezionare più di un file |
accept
Il valore dell'attributo accept
è una stringa che definisce i tipi di file che l'input
accetta.
La stringa è un lista di Identificatori univoci del tipo di file separati da virgola. Poiché un determinato tipo di file può essere identificato in più di un modo, è utile fornire un set completo di identificatori di tipo quando sono necessari file di un determinato formato.
Per esempio, ci sono diversi modi in cui un file di Microsoft Word può essere identificato, quindi un sito che accetta file di Word dovrebbe utilizzare un input
come questo:
<input type="file" id="docpicker"
accept=".doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document">
capture
Il valore dell'attributo capture
è una stringa che specifica quale camera utilizzare per catturare immagini o dati video, se l'attributo accept
indica che l'input possa essere di uno di questi due tipi. Il valore user
indica che devono essere usati il microfono e/o la camera frontali (lato utente). Il valore environment
specifica che devono essere usati il microfono e/o la camera posteriori (lato ambiente). Se l'attributo manca, lo user agent è libero di scegliere quale tra i due utilizzare secodo le proprie specifiche. Se lo strumento di cattura indicato non è presente, lo user agent può far ricadere la scelta sulla propria modalità predefinita.
capture
originariamente era un attributo booleano che, se presente, richiedeva l'utilizzo di un dispositivo di acquisizione multimediale invece del caricamento di un file.files
Un oggetto FileList
che elenca tutti i file selezionati. Questa lista contiene al massimo un elemento, salvo che non sia stato specificato l'attributo multiple
.
multiple
Quando l'attributo booleano multiple
è specificato, il controllo consente di caricare più di un file.
Attributi non standard
Oltre agli atributi elencati sopra, su alcuni browser sono disponibili anche i seguenti attributi. In generale è consigliabile evitarne l'utilizzo laddove possibile, per consentire una completa funzionalità anche sui browser che non li implementano.
Attribute | Description |
---|---|
webkitdirectory |
Un valore booleano che indica se consentire o meno di poter selezionare una o più cartelle (se è presente anche l'attributo |
webkitdirectory
L'attributo booleano webkitdirectory
indica, se presente, che possono essere selezionate solo cartelle nell'interfaccia di selezione dell'utente. Si veda HTMLInputElement.webkitdirectory
per ulteriori esempi.
Note: Anche se originariamente implementato solo per i browser basati su WebKit, l'attributo webkitdirectory
è utilizzabile anche su Microsoft Edge e Firefox 50 o superiori. Comunque, anche se ha un supporto relativemente ampio, non è uno standard e dovrebbe essere evitato laddove non strettamente necessario.
Identificatori univoci del tipo di file
Un identificatore univoco del tipo di file è una stringa che descrive un tipo di file che può essere selezionato dall'utente in una elemento <input>
di tipo file
. Ogni identificatore univoco del tipo di file può avere una delle seguenti forme:
- Una estensione di nomi file valida, che inizia con un carattere di punto ("."). E.g.:
.jpg
,.pdf
o.doc
. - Una stringa identificativa di un MIME-type, senza estensione.
- La stringa
audio/*
ad indicare "qualunque file audio". - La stringa
video/*
ad indicare "qualunque file video". - La stringa
image/*
ad indicare "qualunque file immagine".
L'attributo accept
assume come valore una stringa contenente uno o più di questi identificatori univoci del tipo di file, separati da virgole. Per esempio,
The accept
attribute takes as its value a string containing one or more of these unique file type specifiers, separated by commas. Per esempio, un selettore di file che necessiti di contenuto che possa essere rappresentato come un'immagine, inclusi sia i formati immagine standard che file PDF, potrebbe apparire così:
<input type="file" accept="image/*,.pdf">
Utilizzo degli input di tipo file
Un esempio base
<form method="post" enctype="multipart/form-data">
<div>
<label for="file">Scegli un file da caricare</label>
<input type="file" id="file" name="file" multiple>
</div>
<div>
<button>Invia</button>
</div>
</form>
div {
margin-bottom: 10px;
}
Produce l'output seguente:
Note: Puoi trovare questo esempio, in lingua inglese, anche su GitHub — qui puoi trovarne i sorgenti i sorgenti, ed anche una una dimostrazione di funzionamento.
Indipendentemente dal sistema operativo o dal dispositivo dell'utente, il file input fornisce un bottone che apre una finestra di selezione che consente all'utente di scegliere un file.
Includendo l'attributo multiple
, come mostrato di seguito, specifica che possono essere selezionati più file in un'unica istanza. L'utente può selezionare più file in un qualunque modo consentito dalla propria piattaforma (ad esempio tenendo premuto il tasto Shift o Ctrl, e quindi cliccando). Se si desidera che l'utente scelga un solo file per <input>
è sufficiente omettere l'attributo multiple
.
Ottenere informazioni sui file selezionati
I file selezionati sono restituiti dalla proprietà dell'elemento HTMLInputElement.files
, che è un oggetto FileList
contenente una lista di oggetti File
. La FileList
si comporta come un'array, quindi si può controllarne la proprietà length
per conoscere il numero di file selezionati.
Ogni oggetto File
contiene le seguenti informazioni:
name
- Il nome del file
lastModified
- Un numero che indica la data e l'ora dell'ultima modifica, espressa in millisecondi dalla "UNIX epoch" (1° Gennaio 1970 a mezzanotte).
lastModifiedDate
- Un oggetto
Date
che rappresenta la data e l'ora dell'ultuima modifica. La proprietà è deprecata e non dovrebbe essere utilizzata. Al suo posto utilizzare la proprietàlastModified
. size
- La dimensione del file in byte.
type
- Il MIME-type del file.
webkitRelativePath
- Una stringa che rappresenta il perorso del file relativo alla cartella selezionata in un appostito selettore di cartelle (i.g. un selettore di file in cui l'attributo
webkitdirectory
è stato impostato). Non è una proprietà standard e va utilizzata con attenzione
Note: È possibile leggere e scrivere il valore di HTMLInputElement.files
in tutti i browser più recenti; in Firefox è stato in all modern browsers; su Firefox questa caratteristica è stata aggiunta di recente, nella versione 57 (si veda bug 1384030).
Limitare i tipi di file accettati
Spesso si ha la necessità che l'utente non si libero di selezionare arbitrariamente qualunque tipologia di file; quanto piuttosto consentire che possa selezionare file di un tipo specifico. Per esempio, se un file input consente agli utenti di caricare un'immagine di profilo, molto probabilmente occorrerà consentire solo il aricamento di formati immagine compatibili con il web, come JPEG o PNG.
I tipi di file accettati possono essere specificati con l'attributo accept
, che prende una lista di estensioni consentite o MIME-type, separate da virgola. Ecco alcuni esempi:
accept="image/png"
oaccept=".png"
— Accetta file PNG.accept="image/png, image/jpeg"
oaccept=".png, .jpg, .jpeg"
— Accetta file PNG o JPEG.accept="image/*"
— Accetta qualunque file con MIME-typeimage/*
. (Molti dispositivi mobili consentono all'utente di scattare una foto quando viene specificato questo formato)accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
— accetta qualunque file che sembri un documento di MS Word.
Osserviamo un esempio più completo:
<form method="post" enctype="multipart/form-data">
<div>
<label for="profile_pic">Scegli un file da caricare</label>
<input type="file" id="profile_pic" name="profile_pic"
accept=".jpg, .jpeg, .png">
</div>
<div>
<button>Invia</button>
</div>
</form>
div {
margin-bottom: 10px;
}
Questo produce un output simile a quello dell'esempio precedente:
Note: L'esempio si trova, nella versione inglese, anche su GitHub — qui puoi trovarne i sorgenti ed anche una dimostrazione di funzionamento.
Potrebbe sembrare simile, ma se si prova a selezionare un file, si vedrà che il selettore consente di scegliere solo i tipi di file specificati nell'attributo accept
(il comportamento preciso differisce in base al browser ed al filesystem)
L'attributo accept non valida i tipi dei file selezionati; semplicemente fornisce un suggerimento per il browser per guidare l'utente alla scelta di file del tipo giusto. In molti casi è ancora possibile per l'utente abilitare o disabilitare un'opzione nel selettore di file che rende possibile sovrascrivere questa limitazione e quindi selezionare i file che vuole, scegliendone uno di un tipo non corretto.
A causa di ciò è buona norma accertarsi che l'attributo accept sia corredato da una corretta validazione lato server.
Note
-
Non è possibile impostare il valore di un selettore di file da uno script — una operazione del genere non sortisce alcun effetto:
const input = document.querySelector("input[type=file]"); input.value = "foo";
-
Quando un file viene selezionato usando un
<input type="file">
, il percorso reale del file originale non viene mostrato nell'attributovalue
per ovvie ragioni di sicurezza. Il nome del file invece viene mostrato, con aggiunti il percorso fittizioC:\fakepath\
in cima. -
When a file is chosen using an
<input type="file">
, the real path to the source file is not shown in the input'svalue
attribute for obvious security reasons. Instead, the filename is shown, withC:\fakepath\
appended to the beginning of it. Ci sono alcune ragioni storiche per questa stranezza, ma è supportata da tutti i browser moderni ed in effetti è definita nelle specifiche.
Esempi
In questo esempio mostreremo un selettore di file leggermente più sofisticato, che sfrutta le informazioni sui file disponibili nella proprietà HTMLInputElement.files
, oltre a mostrare qualche trucchetto.
Note: Puoi trovare il sorgente completo della versione inglese di questo esempio si GitHub — file-example.html (click qui per provarne il comportamento dal vivo). Non ne spiegheremo il CSS, essendo il JavaScript l'obiettivo principale.
Per prima cosa osserviamo l'HTML:
<form method="post" enctype="multipart/form-data">
<div>
<label for="image_uploads">Seleziona le immagini da caricare (PNG, JPG)</label>
<input type="file" id="image_uploads" name="image_uploads" accept=".jpg, .jpeg, .png" multiple>
</div>
<div class="preview">
<p>Nessun file attualmente selezionato</p>
</div>
<div>
<button>Invia</button>
</div>
</form>
html {
font-family: sans-serif;
}
form {
width: 580px;
background: #ccc;
margin: 0 auto;
padding: 20px;
border: 1px solid black;
}
form ol {
padding-left: 0;
}
form li, div > p {
background: #eee;
display: flex;
justify-content: space-between;
margin-bottom: 10px;
list-style-type: none;
border: 1px solid black;
}
form img {
height: 64px;
order: 1;
}
form p {
line-height: 32px;
padding-left: 10px;
}
form label, form button {
background-color: #7F9CCB;
padding: 5px 10px;
border-radius: 5px;
border: 1px ridge black;
font-size: 0.8rem;
height: auto;
}
form label:hover, form button:hover {
background-color: #2D5BA3;
color: white;
}
form label:active, form button:active {
background-color: #0D3F8F;
color: white;
}
Questo, ancora una volta, è simile all'esempio precedente - nulla di speciale di cui aggiungere commenti.
Proseguiamo con il JavaScript.
Nelle prime righe dello script ricaviamo i riferimenti all'input stesso della form, e l'elemento <div>
di classe .preview
. In seguito nascondiamo l'elemento <input>
— facciamo questa operazione perchè i file input di solito non hanno un bell'aspetto ed hanno uno stile piuttosto inconsistente tra un browser e l'altro. Si potrà quindi attivare l'elemento input
cliccando sulla sua <label>
, così che sia più comodo nascondele l'input e dare uno stile alla label
simile ad un bottone, così che l'utente sappia che si tratti di un elemento interattivo ed interagisca con questo per caricare i file.
const input = document.querySelector('input');
const preview = document.querySelector('.preview');
input.style.opacity = 0;
Note: La opacity
viene utilizzata per nascondere il file input al posto di visibility: hidden
o display: none
, perchè le tecnologie assistive interpretano gli ultimi due stili come un'indicazione che non si tratti di elementi interattivi.
A questo punto aggiungiamo un "event listener" all'input, che intercetti il cambio di elementi selezionati (in questo caso qundo i file vengono selezionati). L'event listener invoca la nostra funzione updateImageDisplay()
.
input.addEventListener('change', updateImageDisplay);
Quando viene invocata la funzione updateImageDisplay()
:
- Usiamo un loop
while
per svuotare il<div>
del contenuto precedente. - Prendiamo l'oggetto
FileList
che contiene le informazioni di tutti i file selezionati e lo salviamo in una variabile che chiamiamocurFiles
. - Controlliamo che non sia selezionato alcun file, verificando che
curFiles.length
sia ugule a 0, nel qual caso stampiamo un messaggio nel<div>
ad indicare che non ci sono file selezionati. - Se ci sono file selezionati, cicliamo su ciascuno, stampandone le informazioni nel
<div>
di anteprima. Da notare: - Usiamo la funzione
validFileType()
per controllare che il file sia del tipo corretto (e.g. che il tipo di immagine sia tra quelli specificati nell'attributoaccept
). - Se così fosse:
- Stampiamo il nome e la dimensione del file in una lista nel preedente
<div>
. La funzionereturnFileSize()
restituisce una versione formattata della dimensione in bytes/KB/MB (di default il browser riporta una dimensione assoluta in bytes) - Generiamo una anteprima in miniatira dell'immagine chiamando
URL.createObjectURL(curFiles[i])
. Quindi inseriamo l'immagine anche nella lista di oggetti creando un nuovo tag<img>
ed impostando la suasrc
con la miniatura generata.
- Stampiamo il nome e la dimensione del file in una lista nel preedente
- Se il tipo di file non è valido mostriamo un messaggio nella lista di oggetti per indicare all'utente che deve selezionarne uno di un tipo differente.
function updateImageDisplay() {
while(preview.firstChild) {
preview.removeChild(preview.firstChild);
}
const curFiles = input.files;
if(curFiles.length === 0) {
const para = document.createElement('p');
para.textContent = 'Nessun file selezionato per il caricamento';
preview.appendChild(para);
} else {
const list = document.createElement('ol');
preview.appendChild(list);
for(const file of curFiles) {
const listItem = document.createElement('li');
const para = document.createElement('p');
if(validFileType(file)) {
para.textContent = `File ${file.name}, dimensione ${returnFileSize(file.size)}.`;
const image = document.createElement('img');
image.src = URL.createObjectURL(file);
listItem.appendChild(image);
listItem.appendChild(para);
} else {
para.textContent = `File ${file.name}: tipo di file non valido. Aggiorna la tua selezione.`;
listItem.appendChild(para);
}
list.appendChild(listItem);
}
}
}
La funzione personlizzata validFileType()
prende un oggetto File
come parametro, quindi usa Array.prototype.includes()
per verificare che ci sia almeno una corrispondenza con la proprietà type
del file. Se viene trovata una corrispodenza la funzione restituisce il valore true
, altrimenti false
.
// https://developer.mozilla.org/it/docs/Web/Media/Formats/Image_types
const fileTypes = [
"image/apng",
"image/bmp",
"image/gif",
"image/jpeg",
"image/pjpeg",
"image/png",
"image/svg+xml",
"image/tiff",
"image/webp",
"image/x-icon"
];
function validFileType(file) {
return fileTypes.includes(file.type);
}
La funzione returnFileSize()
prende un numero (di byte, preso dalla proprietà size
), e lo trasforma in una stringa correttamente formattata in bytes/KB/MB.
function returnFileSize(number) {
if(number < 1024) {
return number + 'bytes';
} else if(number >= 1024 && number < 1048576) {
return (number/1024).toFixed(1) + 'KB';
} else if(number >= 1048576) {
return (number/1048576).toFixed(1) + 'MB';
}
}
L'esempio è simile al seguente, proviamo:
Specifiche
Specifica | Stato | Commento |
---|---|---|
HTML Living Standard The definition of '<input type="file">' in that specification. |
Living Standard | Definzione iniziale |
HTML 5.1 The definition of '<input type="file">' in that specification. |
Recommendation | Definizione iniziale |
HTML Media Capture The definition of 'capture attribute' in that specification. |
Recommendation | Attributo capture iniziale |
Compatibilità browser
BCD tables only load in the browser
Vedi anche
- Using files from web applications — contiene numerosi altri esempi utili correlati all'
<input type="file">
e alle File API. - Compatibility of CSS properties