venerdì 31 ottobre 2025

C# la gestione dei file con MongoDB e .Net 9

Si riporta l'articolo scritto per il sito https://www.iprogrammatori.it/articoli/database/csharp-gestione-dei-file-mongodb-dotnet-9


In questo articolo vedremo alcune operazioni che si possono fare con il database NoSQL più conosciuto al mondo, MongoDB, ed il linguaggio di programmazione C#, con la versione 9 del Framework .Net
In particolare, l’inserimento, modifica, cancellazione e visualizzazione dei file da gestire tramite database.
Utilizzeremo la versione MongoDB Community, che è la versione gratuita da installare sul pc, e l’ambiente di sviluppo Visual Studio 2022 Community, anch’essa gratuita.

Creazione del progetto

Utilizzando un progetto precedente per la gestione del database MongoDB, come visto negli articoli precedenti (qui https://www.iprogrammatori.it/articoli/microsoft-net-framework/csharp-operazioni-crud-sul-database-mongodb-prima-parte la prima parte delle operazioni CRUD)  in caso di non disponibilità, creare un nuovo progetto di tipo Windows Application, seguendo le prime operazioni descritte nell’articolo indicato. 
Una volta creato il progetto, o aperto uno esistente sempre in ambito di gestione dati di MongoDB, aggiungiamo un nuovo pulsante, nel quale faremo le varie operazioni di gestione. 
Aggiungiamo al progetto 4 pulsante,  uno avrà il nome di tipo “BtnInserisci”, un altro pulsante con il nome del controllo impostato su “BtnModifica”, un altro con il nome “BtnElimina” ed infine l’ultimo, con il valore “BtnVisualizza”. Le proprietà “Text” possiamo impostarle a piacimento, oppure rispettivamente “Inserisci”, “Modifica”, “Elimina”, e “Visualizza”. 
Nel progetto dobbiamo aggiungere tramite Nuget, se non è presente, il pacchetto “MongoDB.Driver”.

Stesura del codice

Passiamo in visualizzazione codice della form, ed in alto sopra ad ogni dichiarazione, inseriamo lo spazio dei nomi per la gestione delle classi per il database MongoDB.
Nella parte in alto, sopra ad ogni dichiarazione, aggiungiamo lo spazio dei nomi, di seguito il frammento delle suddette dichiarazioni.


C#

using MongoDB.Bson;

using MongoDB.Driver;



Facciamo doppio click sul pulsante con il nome “BtnInserisci”,  in modo da passare in visualizzazione codice nell’evento click del pulsante stesso.
Dopo aver creato un oggetto di tipo “MongoClient” per collegarsi al server database, tramite il metodo “GetDatabase”, otteniamo il database di nostro interesse, mentre il metodo “GetCollection”, otteniamo un oggetto di tipo “IMongoCollection” della collection dove vorremmo inserire il file. L’aggiunta del file avviene tramite un oggetto di tipo “BsonDocument”, impostando una proprietà di tipo array dello stream dati del file. 
Il metodo “InsertOne” permette di inserire il dato nella collection.
Di seguito si riporta il frammento di codice delle suddette operazioni.



C#

private void BtnInserisciFile_Click(object sender, EventArgs e)

{

    try

    {

 

        string percorsoNomeFile = "C:\\Varie\\faro.bmp";

        //Rilevo Array byte del file

        byte[] fileArrayBytes = File.ReadAllBytes(percorsoNomeFile);

        //creo un documento BsonDocument con l'array byte del file e altre informazioni

        var nuovoFile = new BsonDocument

        {

            { "NomeFile", Path.GetFileName(percorsoNomeFile) }, // Nome del file

            { "Contenuto",  fileArrayBytes  }, // Contenuto del file come array di byte

            { "tipoFile", Path.GetExtension(percorsoNomeFile) } // tipo file

        };

 

        //Ottengo la collection dati

        var clientMongoDB = new MongoClient("mongodb://localhost:27017");

        var database = clientMongoDB.GetDatabase("Amministrazione");

        var collection = database.GetCollection<BsonDocument>("Dati");

        //Inserisco il nuovo documento nella collection

        collection.InsertOne(nuovoFile);

        MessageBox.Show("File inserito con successo nella collection 'Dati'.");

         

 

    }

    catch (MongoCommandException ex)

    {

        MessageBox.Show(ex.Message);

    }

    catch (Exception ex)

    {

        MessageBox.Show(ex.Message);

    }

}



All’oggetto BsonDocument, possiamo passare una proprietà di tipo “BsonBinaryData”, per dare una migliore definizione al campo del dato .
Di seguito si riporta il frammento di codice di tale utilizzo.


C#

private void BtnInserisciFile_Click(object sender, EventArgs e)

 {

     try

     {

 

 

         //Oggetto del client MongoDB

         var clientMongoDB = new MongoClient("mongodb://localhost:27017");

         //Seleziono il database dal quale rilevare le collection

         var database = clientMongoDB.GetDatabase("Amministrazione");

 

         //Creo una collection per i file nel caso che non esiste

         if (!database.ListCollectionNames().ToList().Contains("Dati"))

         {

             database.CreateCollection("Dati");

         }

         //Seleziono la collection per inserire il file

         var collection = database.GetCollection<BsonDocument>("Dati");

         //Crea un nuovo documento BsonDocument con l'array byte del file e altre informazioni

         var filePath = "C:\\Varie\\faro.jpg";

         if (!File.Exists(filePath))

         {

             MessageBox.Show("Il file specificato non esiste.");

             return;

         }

         var fileBytes = File.ReadAllBytes(filePath);

         //Creo un nuovo documento BsonDocument con il file e altre informazioni

         var nuovoFile = new BsonDocument

         {

             { "NomeFile", Path.GetFileName(filePath) }, // Nome del file

             { "Contenuto", new BsonBinaryData(fileBytes, BsonBinarySubType.Binary) }, // Contenuto del file come array di byte

             { "DataCreazione", DateTime.Now } // Data di creazione del file

         };

          

         collection.InsertOne(nuovoFile);

         MessageBox.Show("File inserito con successo.");

 

     }

     catch (MongoCommandException ex)

     {

         MessageBox.Show(ex.Message);

     }

     catch (Exception ex)

     {

         MessageBox.Show(ex.Message);

     }

 }










Una precisazione sull’inserimento dei file, nel caso che il file supera i 16 MB, verrà generato un errore, come mostrato in figura 1.


Figura 1 – L’errore per un file che supera i 16 MB
Figura 1 – L’errore per un file che supera i 16 MB

In questi casi, occorre usare la classe “GridFSBucket” , che permette di gestire i file di grandi dimensioni.
Per utilizzare questa classe, occorre aggiungere lo spazio dei nomi  “GridFS”, come riportato nel frammento di codice qui di seguito.

C#

using MongoDB.Driver.GridFS;




Per inserire il file di grandi dimensioni, occorre utilizzare il metodo “UploadFromStream”, passando come parametri nome file e lo strem dati del file.
Di seguito il frammento di codice per inserire un file superiore ai 16 MB.


C#

//Oggetto del client MongoDB

var clientMongoDB = new MongoClient("mongodb://localhost:27017");

//Seleziono il database dal quale rilevare le collection

var database = clientMongoDB.GetDatabase("Amministrazione");

var filePath = "C:\\Varie\\file20Mb.dll";

 if (!File.Exists(filePath))

 {

     MessageBox.Show("Il file specificato non esiste.");

     return;

 }

var gridFSbucket = new GridFSBucket(database);

 //Leggo il file e lo converto in array di byte

 using (var fileStream = new FileStream(filePath, FileMode.Open))

 {

     var fileId = gridFSbucket.UploadFromStream(Path.GetFileName(filePath), fileStream);

                   

 }





Il file sarà presente in una “collection” denominata “fs.files”, il tutto come mostrato in figura 2.


Figura 2 – Il fine da 20 mb nella collection per i grandi file


Figura 2 – Il fine da 20 mb nella collection per i grandi file

Passiamo in visualizzazione grafica della form e facciamo doppio click sul pulsante “Visualizza”, in modo da passare in visualizzazione codice nell’evento clic del pulsante.
In questo evento, rileviamo il file di nostro interesse, in particolare applicheremo un filtro per il nome del file, ed una volta ottenuto il documento, tramite la proprietà “AsByteArray” di un documento, rileviamo l’array del file.
Di seguito si riporta il frammento di codice delle suddette operazioni.


C#

private void BtnDownloadFile_Click(object sender, EventArgs e)

{

    try

    {

        //Oggetto del client MongoDB

        var clientMongoDB = new MongoClient("mongodb://localhost:27017");

        //Seleziono il database dal quale rilevare le collection

        var database = clientMongoDB.GetDatabase("Amministrazione");

        //Selezioniono la collection

        var collection = database.GetCollection<BsonDocument>("Dati");

        //Recupero il documento che contiene il file

        var filtro = Builders<BsonDocument>.Filter.Eq("NomeFile", "faro.bmp");

        //rilevo il file

        var documentoFile = collection.Find(filtro).FirstOrDefault();

        if (documentoFile == null)

        {

            MessageBox.Show("Documento non trovato.");

            return;

        }

        //Rilevo l'array di byte del file dal documento

        var fileBytes = documentoFile["Contenuto"].AsByteArray;

        //Variabile per il salvataggio del file

        var percorsoSalvataggio = "C:\\Varie\\faro_scaricato.bmp";

        File.WriteAllBytes(percorsoSalvataggio, fileBytes);

        MessageBox.Show("File scaricato con successo in: " + percorsoSalvataggio);

 

 

 

    }

    catch (MongoCommandException ex)

    {

        MessageBox.Show(ex.Message);

    }

    catch (Exception ex)

    {

        MessageBox.Show(ex.Message);

    }

}




Nel caso che invece si vuole scaricare un file di grandi dimensioni, dobbiamo utilizzare il metodo “DownloadToStream” della classe “GridFsBucket”, che permette di gestire file di grandi dimensioni.
Di seguito si riporta il frammento di codice, che rilevo il documento nella collection “fs.files” dove sono presenti file di grandi dimensioni, ed ottenuto il documento lo scarica.


C#

private void BtnDownloadFile_Click(object sender, EventArgs e)

{

    try

    {

        //Oggetto del client MongoDB

        var clientMongoDB = new MongoClient("mongodb://localhost:27017");

        //Seleziono il database dal quale rilevare le collection

        var database = clientMongoDB.GetDatabase("Amministrazione");

        //Recupero il documento che contiene il file

        var filtro = Builders<BsonDocument>.Filter.Eq("filename", "file20Mb.dll");

        //rilevo il file di grandi dimensioni

        var documentoFile = database.GetCollection<BsonDocument>("fs.files").Find(filtro).FirstOrDefault();

        //Verifico se il documento esiste

        if (documentoFile == null)

        {

            MessageBox.Show("Documento non trovato.");

            return;

        }

        //Rilevo l'id del file

        var fileId = documentoFile["_id"].AsObjectId;

        //Creo un oggetto GridFSBucket per gestire i file di grandi dimensioni

        var gridFSbucket = new GridFSBucket(database);

        //Variabile per il salvataggio del file

        var percorsoSalvataggio = "C:\\Varie\\file20Mb_scaricato.dll";

        //Scarico il file dal database e lo salvo nel percorso specificato

        using (var fileStream = new FileStream(percorsoSalvataggio, FileMode.Create))

        {

            gridFSbucket.DownloadToStream(fileId, fileStream);

        }

        MessageBox.Show("File scaricato con successo in: " + percorsoSalvataggio);

 

 

 

 

 

 

 

 

    }

    catch (MongoCommandException ex)

    {

        MessageBox.Show(ex.Message);

    }

    catch (Exception ex)

    {

        MessageBox.Show(ex.Message);

    }

}







Aggiornamento

Può capitare che in un determinato documento, dovremmo aggiornare il file stesso.
La modifica del campo file, è la stessa tecnica che avviene per modificare i vari campi di un documento, utilizzando il metodo “Set” della classe “Builders”. Tramite il metodo “updateOne” della classe “IMongoCollection”, effettuo le modifiche del documento nella collection.
Tramite la proprietà “ModifiedCount” dell’oggetto “UpdateResult”.
Di seguito si riporta il codice, delle suddette operazioni.


C#

  private void BtnAggiornaFile_Click(object sender, EventArgs e)

 {

     try

     {

 

         //Oggetto del client MongoDB

         var clientMongoDB = new MongoClient("mongodb://localhost:27017");

         //Oggetto per la gestione del database dal quale rilevare le collection

         var database = clientMongoDB.GetDatabase("Amministrazione");

         //Oggetto per la gestione delle collection

         var collection = database.GetCollection<BsonDocument>("Dati");

         //Rilevo il documento da modificare

         var filtro = Builders<BsonDocument>.Filter.Eq("_id", new ObjectId("68a73a8d0d6f07e2909e618c"));

         var documentoFile = collection.Find(filtro).FirstOrDefault();

         string percorsoNomeFile = "C:\\Varie\\faroBiancoNero.jpg";

         // Rilevo Array byte del file

         byte[] fileArrayBytes = File.ReadAllBytes(percorsoNomeFile);

         //Aggiorno il documento con il nuovo file

         var aggiornamento = Builders<BsonDocument>.Update.Set("Contenuto", fileArrayBytes)

                                                          .Set("NomeFile", "nuovo_" + Path.GetFileName(percorsoNomeFile));

         var options = new UpdateOptions { IsUpsert = false }; //Non crea un nuovo documento se non trova quello da aggiornare

         //Aggiorno il documento nella collection

       var risultato =  collection.UpdateOne(filtro, aggiornamento, options);

         //Verifico se è stato aggiornato il documento

         if (risultato.ModifiedCount == 0)

         {

             MessageBox.Show("Nessun documento aggiornato. Verificare l'ID selezionato.");

             return;

         }

         MessageBox.Show("File aggiornato con successo.");

 

 

     }

     catch (MongoCommandException ex)

     {

         MessageBox.Show(ex.Message);

     }

     catch (Exception ex)

     {

         MessageBox.Show(ex.Message);

     }

 }




Nel caso che vogliamo modificare file con dimensione superiori ai 16 MB, dobbiamo utilizzare la classe GridFSBucket. Di seguito si riporta tale utilizzo per l’evento click del pulsante.






private void BtnAggiornaFileGrandiDimensioni_Click(object sender, EventArgs e)

{

    try

    {

 

        //Oggetto del client MongoDB

        var clientMongoDB = new MongoClient("mongodb://localhost:27017");

        //Oggetto per la gestione del database dal quale rilevare le collection

        var database = clientMongoDB.GetDatabase("Amministrazione");

        //Oggetto per la gestione dei grandi file

        var gridFSbucket = new GridFSBucket(database);

        //Elimino il file esistente

        var filtroElimina = Builders<BsonDocument>.Filter.Eq("filename", "file20Mb.dll");

        var documentoFileElimina = database.GetCollection<BsonDocument>("fs.files").Find(filtroElimina).FirstOrDefault();

        if (documentoFileElimina != null)

        {

            var fileIdElimina = documentoFileElimina["_id"].AsObjectId;

            gridFSbucket.Delete(fileIdElimina);

        }

        //Creo un nuovo file

        var filePath = "C:\\Varie\\faropuzzle.jpg";

        if (!File.Exists(filePath))

        {

            MessageBox.Show("Il file specificato non esiste.");

            return;

        }

        //Leggo il file e lo converto in array di byte

        using (var fileStream = new FileStream(filePath, FileMode.Open))

        {

            var fileId = gridFSbucket.UploadFromStream(Path.GetFileName(filePath), fileStream);

        }

                

        MessageBox.Show("File aggiornato con successo.");

 

 

    }

    catch (MongoCommandException ex)

    {

        MessageBox.Show(ex.Message);

    }

    catch (Exception ex)

    {

        MessageBox.Show(ex.Message);

    }

}





Cancellazione

Siamo giunti alla parte conclusiva dell’articolo, ora non resta che vedere una delle varie tecniche per cancellare il valore di un campo del file, ossia eliminare l’array dei byte del file stesso, mantenendo la struttura ed i dati del documento.
La cancellazione del dato in un campo, avviene tramite il metodo “set” della proprietà “Update”, passando come parametro il valore “BsonNull” , dopo aver filtrato il documento in base ad un determinato valore, e consolidando le modifiche tramite il metodo “UpdateOne”, dell’oggetto “IMongoCollection” . Mentre il metodo “UnSet” elimina il campo di un documento, rendendo il documento  senza quel determinato campo. 
Nel frammento di codice qui di seguito, vedremo come tramite il metodo “Set”, della proprietà “Update”, impostiamo il campo del file, con un valore null.
In un evento click del pulsante, scriviamo il codice che permette di cancellare le informazioni del campo (denominato contenuto) impostando con il valore null. 

Passiamo in visualizzazione grafica della nostra form, e facciamo doppio click sul pulsante "BtnElimina", in modo da passare in visualizzazione codice dell'evento click del pulsante.


Di seguito si riporta il codice delle suddette operazioni, con la descrizione dei vari passaggi. 



C#

private void BtnEliminaFile_Click(object sender, EventArgs e)

{

    try

    {

 

        //Oggetto del client MongoDB

        var clientMongoDB = new MongoClient("mongodb://localhost:27017");

        //Oggetto per la gestione del database dal quale rilevare le collection

        var database = clientMongoDB.GetDatabase("Amministrazione");

        //Oggetto per la gestione delle collection

        var collection = database.GetCollection<BsonDocument>("Dati");

        //Rilevo il documento da modificare

        var filtro = Builders<BsonDocument>.Filter.Eq("_id", new ObjectId("68a73a4723525c10b1f3f4ea"));

                                

        //Aggiorno il documento con zero

        var aggiornamento = Builders<BsonDocument>.Update.Set("Contenuto", BsonNull.Value);

        var options = new UpdateOptions { IsUpsert = false }; //Non crea un nuovo documento se non trova quello da aggiornare

                                                              //Aggiorno il documento nella collection

        var risultato = collection.UpdateOne(filtro, aggiornamento, options);

        //Verifico se è stato aggiornato il documento

        if (risultato.ModifiedCount == 0)

        {

            MessageBox.Show("Nessun documento aggiornato. Verificare l'ID selezionato.");

            return;

        }

        MessageBox.Show("File aggiornato con successo.");

 

 

    }

    catch (MongoCommandException ex)

    {

        MessageBox.Show(ex.Message);

    }

    catch (Exception ex)

    {

        MessageBox.Show(ex.Message);

    }

}

 







Conclusioni

L’articolo ha voluto fornire al lettore una panoramica sull’utilizzo della gestione dei file con il database MongoDB Community, affrontando le varie operazioni per comprendere come lavorare sui documenti con i relativi file. La gestione dei file con questo database è un elemento chiave, come lo è per tutti quei progetti di gestione documentale. La flessibilità di questo database di tipo NoSQl, offre al programmatore semplicità nel realizzare nell’immediato applicativi di un certo livello.