Upload de fichier avec API Platform, Symfony et ReactJS
Je vais vous montrer comment uploader un fichier depuis une application en ReactJS vers une API Symfony réalisé avec API Platform
Versions utilisées :
- Symfony 5.3
- API Platform 2.6.5
- ReactJS : 17.0.0
La partie Back avec Symfony et API Platform
Pour commencer, je vous invite à suivre le
tutoriel du site API Platform
pour réaliser la partie API de votre application. C’est ce que j’ai utilisé pour mettre en place mon API me permettant d’uploader des fichiers simplement. Dans le tutoriel, j’ai choisi d’avoir une Entity MediaObject à part, qui n’est donc pas intégré à une autre Entity de mon application. Je vais donc avoir une route
/api/media_objects
pour uploader mon fichier.
Passons au front avec ReactJS
Passons à la partie front en ReactJS. Je vais prendre un simple formulaire qui uploade un fichier comme ceci :
import React from 'react';
import { FormControlLabel } from '@material-ui/core';
import { Controller, useForm } from 'react-hook-form';
export default function Upload() {
const {
control, handleSubmit, setValue, getValues
} = useForm();
const onSubmit = (data) => {
console.log('Formulaire envoyé');
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="file"
accept="image/*"
control={control}
render={({ field, fieldState }) => (
<FormControlLabel
label="File"
control={(
<input
type="file"
accept="image/*"
{...field.name}
{...fieldState}
name="file"
onChange={(e) => setValue('file', e.target.files[0])}
/>
)}
labelPlacement="start"
/>
)}
/>
<input type="submit" value="Envoyer" />
</form>
);
}
Un peu d’explication. Pour avoir le contrôle de mon input de type file j’utilise le composant
Controller
qui me permet d’avoir la fonction
onChange
de mon input et de sauvegarder le fichier dans un state. J’utilise également quelques fonctions de
useForm
pour faciliter la gestion du formulaire.
Pour le moment, mon composant
Upload
n’est qu’un simple input de type file avec un bouton pour envoyer le formulaire. Un message dans la console s’affiche lorsque je soumets le formulaire. Je vais pouvoir effectuer l’envoi de ce fichier vers mon API. Pour cela, je vais utiliser
fetch
pour effectuer mes requêtes HTTP facilement. Il existe aussi
axios
si vous voulez y jeter un oeil.
Envoi du fichier via la fonction fetch
Voici le code qui va me permettre d’envoyer mon ficher à mon API :
const sendFile = async (file) => {
const form = new FormData();
form.append('file', file);
const response = await apiCall('/api/media_objects', 'POST', form);
return response.json.id;
};
const apiCall = async (endpoint, method = 'GET', data = null, headers = null) => {
const res = await fetch(endpoint, {
method,
headers: {
...headers,
},
body: data,
//mode: 'no-cors',
});
const text = await res.text();
let json = {};
if (text !== '') {
json = JSON.parse(text);
}
return {
status: res.status,
json,
};
};
La fonction
sendFile
permet de formater la donnée pour pouvoir l’envoyer à dans le bon format.
Ma fonction
apiCall
permet d’envoyer le fichier à mon API et de gérer la réponse de retour.
Problèmes CORS
ATTENTION :
En travaillant en local, il y a souvent des erreurs CORS. Dans mon cas, je travaille avec
nelmio/cors-bundle
côté Symfony. Côté ReactJS et plus précisément sur la fonction
fetch
, il y a la possibilité d’ajouter le mode
no-cors
. Mais l’ajout de ce mode dans mon cas m’empêchait de faire ma requête HTTP sans erreur. C’est pour cela que je l’ai mis en commentaire dans mon exemple.
Code ReactJS complet
import React from 'react';
import { FormControlLabel } from '@material-ui/core';
import { Controller, useForm } from 'react-hook-form';
export default function Upload() {
const {
control, handleSubmit, setValue, getValues,
} = useForm();
const apiCall = async (endpoint, method = 'GET', data = null, headers = null) => {
const res = await fetch(endpoint, {
method,
headers: {
...headers,
},
body: data,
//mode: 'no-cors',
});
const text = await res.text();
let json = {};
if (text !== '') {
json = JSON.parse(text);
}
return {
status: res.status,
json,
};
};
const sendFile = async (file) => {
const form = new FormData();
form.append('file', file);
const response = await apiCall('/api/media_objects', 'POST', form);
return response.json.id;
};
const onSubmit = async () => {
const response = await sendFile(getValues('file'));
console.log(response);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="file"
accept="image/*"
control={control}
render={({ field, fieldState }) => (
<FormControlLabel
label="File"
control={(
<input
type="file"
accept="image/*"
{...field.name}
{...fieldState}
name="file"
onChange={(e) => setValue('file', e.target.files[0])}
/>
)}
labelPlacement="start"
/>
)}
/>
<input type="submit" value="Envoyer" />
</form>
);
}
Et voilà comment envoyer un fichier depuis une application ReactJS vers son API Symfony géré avec API Platform.
Derniers articles
Retrouvez mes derniers articles ci-dessous autour des thérapeutes bien-être et des coachs.
Pourquoi faire appel à un professionnel pour créer son site internet en tant que thérapeute ou coach
Découvrez pourquoi un site professionnel est essentiel pour thérapeutes et coachs, avec des conseils sur la visibilité et un accompagnement personnalisé.
Lire plusPourquoi un site web est essentiel pour un thérapeute ?
Découvrez 8 raisons clés pour lesquelles un site web est indispensable aux thérapeutes : visibilité, crédibilité et génération de nouveaux clients
Lire plusStarter Kit Symfony 7 pour Développeurs Web
Découvrez le Starter Kit Symfony 7 : Gagnez du temps sur vos projets web avec des fonctionnalités préconfigurées !"
Lire plus