La selezione e l'interazione con i file sul dispositivo locale dell'utente è una delle funzionalità più utilizzate del web. Consente agli utenti di selezionare i file e caricarli su un server, ad esempio quando condividono foto o inviano documenti fiscali. Consente inoltre ai siti di leggerli e manipolarli senza dover mai trasferire i dati sulla rete. Questa pagina descrive come utilizzare JavaScript per interagire con i file.
La moderna API File System Access
L'API File System Access fornisce un modo per leggere e scrivere file e directory sul sistema locale dell'utente. È disponibile nella maggior parte dei browser basati su Chromium, come Chrome ed Edge. Per saperne di più, consulta l'API File System Access.
Poiché l'API File System Access non è compatibile con tutti i browser, ti consigliamo di utilizzare browser-fs-access, una libreria helper che utilizza la nuova API ovunque sia disponibile e ricorre ad approcci legacy quando non lo è.
Lavorare con i file nel modo classico
Questa guida mostra come interagire con i file utilizzando i metodi JavaScript legacy.
Seleziona file
Esistono due modi principali per selezionare i file: utilizzando l'elemento di input HTML e utilizzando una zona di trascinamento.
Elemento di input HTML
Il modo più semplice per gli utenti di selezionare i file è utilizzare l'elemento
<input type="file">
, supportato in tutti i principali browser. Se viene selezionato, consente a un utente di selezionare un file o più file se è incluso l'attributo
multiple
, utilizzando l'interfaccia utente di selezione dei file integrata del sistema operativo. Quando l'utente termina la selezione di uno o più file, viene attivato l'evento change
dell'elemento. Puoi accedere all'elenco dei file da event.target.files
, che
è un oggetto FileList
.
Ogni elemento in FileList
è un oggetto File
.
<!-- The `multiple` attribute lets users select multiple files. -->
<input type="file" id="file-selector" multiple>
<script>
const fileSelector = document.getElementById('file-selector');
fileSelector.addEventListener('change', (event) => {
const fileList = event.target.files;
console.log(fileList);
});
</script>
L'esempio seguente consente a un utente di selezionare più file utilizzando l'interfaccia utente di selezione dei file integrata nel sistema operativo e poi registra ogni file selezionato nella console.
Limitare i tipi di file che gli utenti possono selezionare
In alcuni casi, potresti voler limitare i tipi di file che gli utenti possono selezionare. Ad esempio, un'app di modifica delle immagini dovrebbe accettare solo immagini, non file di testo. Per impostare
limitazioni per i tipi di file, aggiungi un
attributo accept
all'elemento di input per specificare i tipi di file accettati:
<input type="file" id="file-selector" accept=".jpg, .jpeg, .png">
Trascinamento personalizzato
In alcuni browser, l'elemento <input type="file">
è anche una destinazione di rilascio,
che consente agli utenti di trascinare i file nella tua app. Tuttavia, questa destinazione di rilascio
è piccola e può essere difficile da usare. Invece, dopo aver fornito le funzionalità di base utilizzando
un elemento <input type="file">
, puoi fornire una superficie di trascinamento personalizzata di grandi dimensioni.
Scegliere la zona di rilascio
La superficie di rilascio dipende dal design dell'applicazione. Potresti voler utilizzare solo una parte della finestra come superficie di rilascio, ma puoi utilizzare l'intera finestra.

L'app di compressione delle immagini Squoosh consente all'utente di trascinare un'immagine in un punto qualsiasi della
finestra e fare clic su Seleziona un'immagine per richiamare l'elemento <input type="file">
. Qualunque sia la zona di rilascio che scegli, assicurati che sia chiaro all'utente
che può trascinare i file su quella superficie.
Definisci la zona di rilascio
Per attivare un elemento come zona di trascinamento, crea listener per
due eventi: dragover
e drop
.
L'evento dragover
aggiorna la UI del browser per indicare visivamente che l'azione
di trascinamento sta creando una copia del file. L'evento drop
viene attivato
dopo che l'utente rilascia i file sulla superficie. Come per l'elemento di input, puoi accedere all'elenco dei file da event.dataTransfer.files
, che è un oggetto FileList
. Ogni
elemento di FileList
è un oggetto File
.
const dropArea = document.getElementById('drop-area');
dropArea.addEventListener('dragover', (event) => {
event.stopPropagation();
event.preventDefault();
// Style the drag-and-drop as a "copy file" operation.
event.dataTransfer.dropEffect = 'copy';
});
dropArea.addEventListener('drop', (event) => {
event.stopPropagation();
event.preventDefault();
const fileList = event.dataTransfer.files;
console.log(fileList);
});
event.stopPropagation()
e event.preventDefault()
interrompono il comportamento predefinito del browser e consentono l'esecuzione del codice. Senza, il browser uscirebbe dalla pagina e aprirebbe i file che l'utente ha trascinato nella finestra del browser.
Per una dimostrazione dal vivo, consulta Trascinamento personalizzato.
E le directory?
Purtroppo non esiste un modo semplice per accedere a una directory utilizzando JavaScript.
L'attributo webkitdirectory
nell'elemento <input type="file">
consente all'utente di scegliere una o più directory. È supportato nella maggior parte dei principali browser,
ad eccezione di Firefox per Android e Safari su iOS.
Se il trascinamento è abilitato, un utente potrebbe provare a trascinare una directory nell'area di rilascio. Quando viene attivato l'evento di rilascio, include un oggetto File
per la
directory, ma non fornisce l'accesso a nessuno dei file nella directory.
Leggi i metadati del file
L'oggetto File
contiene metadati sul file. La maggior parte dei browser
fornisce il nome, le dimensioni e il tipo MIME del file, anche se a seconda
della piattaforma, browser diversi potrebbero fornire informazioni diverse o aggiuntive.
function getMetadataForFileList(fileList) {
for (const file of fileList) {
// Not supported in Safari for iOS.
const name = file.name ? file.name : 'NOT SUPPORTED';
// Not supported in Firefox for Android or Opera for Android.
const type = file.type ? file.type : 'NOT SUPPORTED';
// Unknown cross-browser support.
const size = file.size ? file.size : 'NOT SUPPORTED';
console.log({file, name, type, size});
}
}
Puoi vedere questa funzionalità in azione nella input-type-file
demo.
Leggere il contenuto di un file
Utilizza FileReader
per
leggere il contenuto di un oggetto File
in memoria. Puoi indicare a FileReader
di
leggere un file come buffer di array,
un URL dati
o un testo:
function readImage(file) {
// Check if the file is an image.
if (file.type && !file.type.startsWith('image/')) {
console.log('File is not an image.', file.type, file);
return;
}
const reader = new FileReader();
reader.addEventListener('load', (event) => {
img.src = event.target.result;
});
reader.readAsDataURL(file);
}
Questo esempio legge un File
fornito dall'utente, lo converte in un URL dati e utilizza questo URL dati per visualizzare l'immagine in un elemento img
.
Per scoprire come verificare che l'utente abbia selezionato un file immagine, consulta la demo
read-image-file
.
Monitorare l'avanzamento della lettura di un file
Quando si leggono file di grandi dimensioni, può essere utile fornire un po' di UX per comunicare all'utente
a che punto è la lettura. A questo scopo, utilizza l'evento
progress
fornito da FileReader
. L'evento progress
ha due proprietà:
loaded
(l'importo letto) e total
(l'importo da leggere).
function readFile(file) {
const reader = new FileReader();
reader.addEventListener('load', (event) => {
const result = event.target.result;
// Do something with result
});
reader.addEventListener('progress', (event) => {
if (event.loaded && event.total) {
const percent = (event.loaded / event.total) * 100;
console.log(`Progress: ${Math.round(percent)}`);
}
});
reader.readAsDataURL(file);
}
Immagine hero di Vincent Botta da Unsplash