30-3 Préparation du téléversement et lecture du contenu du fichier
Maintenant que nous avons un endroit central où stocker les fichiers, on peut entamer le téléversement de fichiers.
La première étape est d'avoir un champ de formulaire pour ajouter un fichier.
Blazor offre un composant <InputFile>
pour afficher un input
de type file
Ajouter un champ InputFile
au formulaire
Dans le composant pour créer un nouvel événement (New
), ajoutez un nouveau champ InputFile
(ici, il est directement dans le haut du formulaire):
<!-- ... -->
<div class="col-lg-6">
<EditForm Model="evenementDto" OnValidSubmit="@CreerEvenement">
<DataAnnotationsValidator />
<div class="mb-3">
<label for="image" class="form-label">@LocalizerEvenementDto["Image"]</label>
<InputFile id="image" class="form-control" accept=".jpg, .jpeg, .png" />
</div>
<!-- ... -->
Il est possible de spécifier les types de fichiers acceptés via accept=
.
Comme on veut une image, on indique les extensions d'images standards.
Détecter les changements au InputFile
Lorsqu'une image sera sélectionnée, on procédera immédiatement à l'envoi du fichier pour stockage.
La stratégie est différente de si on avait un formulaire rendu serveur un peu plus classique comme MVC
où on pourrait faire l'envoi du fichier en même temps que le reste du formulaire.
Ici, si on voulait faire cela, il faudrait convertir le contenu de l'image en base64, assigner ce contenu à une propriété du DTO et poursuivre la sauvegarde côté serveur. Cela est fonctionnel, mais rend la requête très grosse en plus de ne pas être très flexible dans le cas où plusieurs fichiers seraient à téléverser en même temps.
Une approche fréquente est de simplement téléverser le fichier et si jamais il n'est pas utilisé (parce que le formulaire n'a pas été soumis), un processus de "ménage" passe en arrière-plan quelques fois par jour ou par semaine pour faire le ménage des fichiers inutilisé. Cependant, on ne s'occupera pas trop de cet aspect pour l'instant.
Pour détecter les changements, on vient lier la propriété onchange
à une fonction de la composante dans la portion @code
:
<!-- ... -->
<div class="mb-3">
<label for="image" class="form-label">Image</label>
<InputFile id="image" class="form-control" accept=".jpg, .jpeg, .png" OnChange="@OnInputFileChange" />
</div>
<!-- ... -->
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
// Un fichier a été sélectionné à partir du champ image
}
Lire le contenu du fichier et préparer la requête
Lorsqu'on envoie un fichier, on l'envoie en format binaire. Pour ce faire, il est nécessaire de lire le contenu du fichier.
Pour l'envoi du fichier en format binaire, on utilisera un type d'encodage particulier: multipart/form-data
Le format multipart/form-data est un type d'encodage utilisé pour transmettre des données de formulaire, y compris des fichiers binaires, à travers des requêtes HTTP. Il est souvent utilisé pour le téléchargement de fichiers dans les applications Web.
Pour envoyer des données multipart/form-data à l'aide de HttpClient, vous pouvez utiliser la classe MultipartFormDataContent et ajouter des instances de ByteArrayContent, StringContent ou StreamContent pour représenter les données des champs de formulaire.
Dans le cas qui nous occupe, on utilise StreamContent
qui correspond à la sortie de la lecture du fichier.
- On créera dans un premier temps deux variables: une pour spécifier la taille maximale des fichiers acceptés et une deuxième qui servira à valider que le fichier est prêt à être envoyé vers le serveur.
Snowfall.Web.ClientAdmin/Pages/Evenements/New.razor
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
// La taille maximale acceptés pour les fichiers (5 Mo)
long tailleFichierMax = 1024 * 1024 * 5;
// Variable permettant de contrôler si on procède ou non au téléversement
bool estPretPourUpload = false;
} - Un objet de type
MultipartFormDataContent
est créé pour concenir le contenu du fichier.Snowfall.Web.ClientAdmin/Pages/Evenements/New.razorprivate async Task OnInputFileChange(InputFileChangeEventArgs e)
{
// La taille maximale acceptés pour les fichiers (5 Mo)
long tailleFichierMax = 1024 * 1024 * 5;
// Variable permettant de contrôler si on procède ou non au téléversement
bool estPretPourUpload = false;
// On crée le contenu du "formulaire" (body) envoyé
using var content = new MultipartFormDataContent();
} - Finalement, on fait la lecture du fichier et on l'assigne à la variable
content
de typeMultipartFormDataContent
.Snowfall.Web.ClientAdmin/Pages/Evenements/New.razorprivate async Task OnInputFileChange(InputFileChangeEventArgs e)
{
// La taille maximale acceptés pour les fichiers (5 Mo)
long tailleFichierMax = 1024 * 1024 * 5;
// Variable permettant de contrôler si on procède ou non au téléversement
var estPretPourUpload = false;
// On crée le contenu du "formulaire" (body) envoyé
using var content = new MultipartFormDataContent();
try
{
// Le fichier est récupéré à partir de l'événement
IBrowserFile file = e.File;
// Le contenu du fichier est récupéré, avec comme limite tailleFichierMax
var fileContent =
new StreamContent(file.OpenReadStream(tailleFichierMax));
// On assigne le bon type de fichier au contenu
fileContent.Headers.ContentType =
new MediaTypeHeaderValue(file.ContentType);
// Le body de la requête qui sera envoyée
content.Add(
content: fileContent,
name: "\"file\"",
fileName: file.Name);
// Aucune erreur, on peut procéder à l'upload
estPretPourUpload = true;
}
catch (Exception ex)
{
ToastService.Notify(new(ToastType.Danger, "Impossible de lire le fichier. Vérifiez qu'il correspond bien à la taille maximale."));
}
}
Cela devrait nous permettre de lire le contenu du fichier, mais pas encore de l'envoyer. C'est pourquoi on assigne à la variable estPretPourUpload
la valeur de true
.
Pour envoyer le fichier et le stocker sur le serveur, un point de terminaison (action) d'API sera nécéssaire.