X

Comment télécharger des fichiers avec React






📣

Si vous recherchez un simple composant de téléchargement de fichiers, consultez Uppy.

TĂ©lĂ©chargement d’un seul fichier

Pour tĂ©lĂ©charger un seul fichier dans React, vous devez dĂ©finir le content-type et content-length en-tĂȘtes et indiquez le contenu du fichier comme corps de la requĂȘte :

import { ChangeEvent, useState } from 'react';

function FileUploadSingle() {
  const [file, setFile] = useState<File>();

  const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    if (e.target.files) {
      setFile(e.target.files[0]);
    }
  };

  const handleUploadClick = () => {
    if (!file) {
      return;
    }

    // 👇 Uploading the file using the fetch API to the server
    fetch('https://httpbin.org/post', {
      method: 'POST',
      body: file,
      // 👇 Set headers manually for single file upload
      headers: {
        'content-type': file.type,
        'content-length': `${file.size}`, // 👈 Headers need to be a string
      },
    })
      .then((res) => res.json())
      .then((data) => console.log(data))
      .catch((err) => console.error(err));
  };

  return (
    <div>
      <input type="file" onChange={handleFileChange} />

      <div>{file && `${file.name} - ${file.type}`}</div>

      <button onClick={handleUploadClick}>Upload</button>
    </div>
  );
}

export default FileUploadSingle;
  1. Tout d’abord, nous ajoutons un input Ă©lĂ©ment avec type="file" attribut.
  2. Nous pouvons stocker le fichier sĂ©lectionnĂ© dans l’état du composant React, aprĂšs l’avoir reçu du onChange Ă©vĂ©nement. Comme nous ne pouvons sĂ©lectionner qu’un seul fichier, nous pouvons l’obtenir Ă  partir du files tableau sur l’entrĂ©e : e.target.files[0].
  3. Nous pouvons tĂ©lĂ©charger le fichier Ă  l’aide de l’API Fetch. Nous devons dĂ©finir l’ensemble body au fichier que nous avons reçu de l’entrĂ©e et des en-tĂȘtes : content-type au dossier type et le content-length pour file.size. Notez que les en-tĂȘtes doivent ĂȘtre des valeurs de chaĂźne.

J’ai utilisĂ© une API httpbin.org qui accepte les tĂ©lĂ©chargements de fichiers et rĂ©pond avec une copie de la demande que vous envoyez. Voici le rĂ©sultat :

Démo du téléchargement de fichier unique.

Téléchargement de plusieurs fichiers

Pour tĂ©lĂ©charger plusieurs fichiers Ă  partir de input Ă©lĂ©ment dans React, vous devez utiliser l’API JavaScript FormData et encoder la demande comme multipart/form-data.

import { ChangeEvent, useState } from 'react';

function FileUploadMultiple() {
  const [fileList, setFileList] = useState<FileList | null>(null);

  const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    setFileList(e.target.files);
  };

  const handleUploadClick = () => {
    if (!fileList) {
      return;
    }

    // 👇 Create new FormData object and append files
    const data = new FormData();
    files.forEach((file, i) => {
      data.append(`file-${i}`, file, file.name);
    });

    // 👇 Uploading the files using the fetch API to the server
    fetch('https://httpbin.org/post', {
      method: 'POST',
      body: data,
    })
      .then((res) => res.json())
      .then((data) => console.log(data))
      .catch((err) => console.error(err));
  };

  // 👇 files is not an array, but it's iterable, spread to get an array of files
  const files = fileList ? [...fileList] : [];

  return (
    <div>
      <input type="file" onChange={handleFileChange} multiple />

      <ul>
        {files.map((file, i) => (
          <li key={i}>
            {file.name} - {file.type}
          </li>
        ))}
      </ul>

      <button onClick={handleUploadClick}>Upload</button>
    </div>
  );
}

export default FileUploadMultiple;
TĂ©lĂ©chargement de plusieurs fichiers Ă  l’aide de FormData dans ReactJS.

La premiĂšre diffĂ©rence par rapport Ă  notre exemple de tĂ©lĂ©chargement de fichier unique est l’ajout de multiple attribut sur le input Ă©lĂ©ment.

Au lieu de stocker un seul fichier dans l’état du composant React, nous enregistrons l’ensemble FileList en Ă©tat

📣

Notez que le FileList n’est pas un tableau, nous ne pouvons donc pas utiliser des mĂ©thodes de tableau rĂ©guliĂšres comme map ou forEach. Cependant, nous pouvons toujours accĂ©der aux membres par index fileList[0]parcourez les fichiers en utilisant for..of ou les rĂ©pandre.

Pour télécharger plusieurs fichiers :

  1. Créer un FormData objet: const data = new FormData();
  2. Ajoutez chaque fichier que vous souhaitez tĂ©lĂ©charger Ă  l’aide de FormData.append() – il accepte un nom de champ de formulaire, le fichier et un nom de fichier comme paramĂštres.
  3. À l’aide de l’API Fetch, tĂ©lĂ©chargez les fichiers en dĂ©finissant les donnĂ©es du formulaire comme body. Notez que lorsque vous utilisez des donnĂ©es de formulaire, vous n’avez pas besoin de dĂ©finir les en-tĂȘtes manuellement. Il est pris en charge par l’API de rĂ©cupĂ©ration.

Voici à quoi ça ressemble :

Démo de téléchargement multi-fichiers.

Personnalisation de l’entrĂ©e du fichier

Le dĂ©faut input L’élĂ©ment n’offre pas grand-chose en termes de style. Pour crĂ©er une entrĂ©e de tĂ©lĂ©chargement de fichier personnalisĂ©e dans React, vous devrez masquer l’entrĂ©e de tĂ©lĂ©chargement de fichier natif et dĂ©clencher le click Ă©vĂ©nements sur l’entrĂ©e Ă  l’aide de refs :

import { ChangeEvent, useRef, useState } from 'react';

function CustomFileInput() {
  const [file, setFile] = useState<File>();
  const inputRef = useRef<HTMLInputElement | null>(null);

  const handleUploadClick = () => {
    // 👇 We redirect the click event onto the hidden input element
    inputRef.current?.click();
  };

  const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    if (!e.target.files) {
      return;
    }

    setFile(e.target.files[0]);

    // đŸš© do the file upload here normally...
  };

  return (
    <div>
      <div>Upload a file:</div>

      {/* 👇 Our custom button to select and upload a file */}
      <button onClick={handleUploadClick}>
        {file ? `${file.name}` : 'Click to select'}
      </button>

      {/* 👇 Notice the `display: hidden` on the input */}
      <input
        type="file"
        ref={inputRef}
        onChange={handleFileChange}
        style={{ display: 'none' }}
      />
    </div>
  );
}
CrĂ©ation d’un composant d’entrĂ©e de fichier personnalisĂ© dans React.

Seulement le input L’élĂ©ment avec le type de fichier peut ouvrir les fichiers Ă  sĂ©lectionner dans le navigateur. Pour tĂ©lĂ©charger un fichier en cliquant sur le bouton personnalisĂ©, nous devons dĂ©clencher le click() Ă©vĂ©nement sur l’entrĂ©e : inputRef.current?.click();

Si nous ne voulons pas afficher l’entrĂ©e native, nous pouvons la masquer en ajoutant le display: none propriĂ©tĂ© CSS dans son style ou en appliquant une classe CSS qui dĂ©finit la propriĂ©tĂ© d’affichage sur none (par exemple, dans Tailwind, le nom de la classe est hidden).

DĂšs lors, vous pouvez enregistrer les fichiers sĂ©lectionnĂ©s dans l’état ou les tĂ©lĂ©charger immĂ©diatement. Vous avez maintenant une personnalisation complĂšte de l’entrĂ©e de tĂ©lĂ©chargement de fichier :

DĂ©mo d’une entrĂ©e de fichier personnalisĂ©e.

Conclusion

Dans React, le tĂ©lĂ©chargement de fichiers est implĂ©mentĂ© en utilisant le code HTML input Ă©lĂ©ment et du JavaScript pour faire une requĂȘte POST/PUT au serveur avec le FormData qui contient les fichiers sĂ©lectionnĂ©s.

Votre serveur devra alors traiter les donnĂ©es du formulaire en plusieurs parties pour accepter les tĂ©lĂ©chargements de fichiers. Vous pouvez utiliser Multer dans Node.js pour implĂ©menter cela ou tĂ©lĂ©charger les fichiers directement sur Amazon S3 si c’est ce que vous voulez.

Comme toujours, trouvez le code utilisé dans les exemples de mon référentiel GitHub.