Thursday, July 4, 2024
HomePHPA number of File Add in React with Progress Bar

A number of File Add in React with Progress Bar


by Vincy. Final modified on December 1st, 2023.

The multi-file add is a function that enables customers to carry out a bulk file add. It saves customers the hassle of choosing every file one after the other.

In a earlier tutorial, we’ve got seen how one can create a React element for a single file add. On this tutorial, we assist multi-file add by processing an array of information uploaded by customers.

View demo

This instance reveals a progress bar to point out the importing progress. For the reason that multi-file add takes a major time, this progress bar will likely be useful to know the standing.

multiple file upload react

Steps to a number of file add utilizing React

  1. Create A number of information add React element and render to the UI.
  2. Bind UI controls with the JS handlers to entry information and set off the add.
  3. Acknowledge customers with a progress bar and previews.

Create A number of information add React parts and render to the UI

On this instance, we use CDN and babel transpiler to construct a React element with a JSX.

This React instance contains the CDN path of React, ReactDOM, Axios and Babel libraries.

Word: The CDN primarily based transpilation just isn’t beneficial for manufacturing. Quite, depend upon any construct instrument like Webpack.

Within the earlier article, we use Vite instrument which performs babel tranpilation with respect to the babel.config.js in the course of the construct for manufacturing.

The React element class do the next.

  • It binds the a number of file add variables with the corresponding setters.
  • It defines a management to reset all of the variables to the preliminary state.
  • It returns JSX for the multi-file add possibility and preview UI with progress bar.

The React element created on this instance is MultiFileUpload. That is rendered into the HTML root created for deploying this React element by way of ReactDOM.

Initially, the UI reveals the file enter to add a number of information. As soon as the chosen information are submitted, then the preview and progress bar HTML parts will likely be proven.

This situation is checked primarily based on the useState of the counter that has the variety of information posted on submit.

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta title="viewport" content material="width=device-width, initial-scale=1.0" />
  <hyperlink rel="stylesheet" href="https://phppot.com/react/react-multiple-file-upload/type.css" />
  <hyperlink rel="stylesheet" href="type.css" />
  <title>A number of File Add</title>
</head>

<physique>
  <h1>A number of File Add</h1>
  <div id="multiple-file-upload-component"></div>

  <script src="https://unpkg.com/react@17/umd/react.growth.js"></script>
  <script src="https://unpkg.com/react-dom@17/umd/react-dom.growth.js"></script>
  <script src="https://cdn.jsdelivr.web/npm/axios/dist/axios.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script src="multiple-file-upload.js"></script>

  <script kind="textual content/babel">
    const { useState } = React;
    const { render } = ReactDOM;

    const MultiFileUpload = () => {
      const [files, setFiles] = useState([]);
      const [errorMessage, setErrorMessage] = useState("");
      const [uploadProgress, setUploadProgress] = useState(0);
      const [imagePreview, setImagePreview] = useState([]);
      const [uploadButtonClicked, setUploadButtonClicked] = useState(false);

      perform clearState() {
        setFiles([]);
        setErrorMessage("");
        setUploadProgress(0);
        setImagePreview([]);
        setUploadButtonClicked(false);
      }
      return (
        <div>
          {errorMessage && <p className="validation-message">{errorMessage}</p>}
          <div className="file-upload-button">
            <enter
              kind="file"
              a number of
              settle for="picture/jpeg, picture/png, picture/gif"
              onChange={handleFileOnChange}
            />
            <button onClick={handleMultiFileUpload}>Add</button>
          </div>
          {uploadButtonClicked && (
            <div>
              <div className="image-container">
                {information.size > 0 && (
                  <div>
                    <h3>Preview :</h3>
                  </div>
                )}
                {information.map((file, index) => (
                  <div key={index} type={{ marginBottom: "10px" }}>
                    <div>
                      <img className="preview" src={imagePreview[index]} alt="Preview" />
                    </div>
                  </div>
                ))}
              </div>
              <div className="progress-bar">
                <div
                  className="progress-fill"
                  type={{ width: `${uploadProgress}%` }}
                ></div>
              </div>
            </div>
          )}
        </div>
      );
    };
    ReactDOM.render(<MultiFileUpload />, doc.getElementById("multiple-file-upload-component"));
  </script>
</physique>

</html>

Bind UI controls with the JS handlers to entry information and set off the add

This JavaScript comprises features for validating the uploaded file. After validation, it triggers an AJAX request to carry out the server-side add motion if no error exists.

The validation is for ensuring of the next circumstances.

  • It checks if the file is throughout the allowed dimension restrict.
  • It checks the file extension is one among the many allowed sorts. These are the jpg, png and gif kind of pictures that may solely be uploaded by this instance.

As soon as no error discovered and the add request is posted, the a number of pictures preview are proven. The setImagePreviews() methodology change the UI state with the not too long ago uploaded picture preview.

multiple-file-upload.js

perform checkIsAllowedType(selectedFiles) {
  const allowedTypes = ['.jpeg', '.png', '.gif'];
  return selectedFiles.some(file => {
    const fileExtension = file.title.cut up('.').pop().toLowerCase();
    return allowedTypes.contains(`.${fileExtension}`);
  });
}
async perform handleMultipleFileUploadAjax(information, setUploadProgress, setErrorMessage) {
  strive {
    const formData = new FormData();
    information.forEach((file) => formData.append('file', file));

    const response = await axios.put up('upload-image.php', formData, {
      onUploadProgress: (progressEvent) => {
        const percentCompleted = Math.spherical((progressEvent.loaded * 100) / progressEvent.complete);
      },
    });

    console.log(response.knowledge);
  } catch (error) {
    console.error(error);
  }
}

const validateFile = (e, setFiles, setErrorMessage, setImagePreviews, clearState) => {
  clearState();
  const selectedFiles = Array.from(e.goal.information);
  const totalSize = selectedFiles.scale back((acc, file) => acc + file.dimension, 0);
  if (totalSize > 2 * 1024 * 1024) {
    setErrorMessage('Picture dimension exceeds. It must be lower than 2MB.');
  } else {
    const isAllowedFiles = checkIsAllowedType(selectedFiles);
    if (!isAllowedFiles) {
      setErrorMessage('Please choose solely picture information (jpeg, png, gif).');
    } else {
      setFiles(selectedFiles);
      const previews = selectedFiles.map((file) => URL.createObjectURL(file));
      setImagePreviews(previews);
    }
  }
};

Acknowledge customers with a progress bar and previews

This code is as a part of the MultiFileUpload element definition. These two handlers calls setters setImagePreview and setUploadProgress to point out the graphical acknowledgement for the consumer motion.

It updates the UI with the uploaded picture thumbnails as preview. It additionally updates the share of add accomplished in a sliding progress bar.

const handleFileOnChange = (e) => {
    validateFile(
      e,
      setFiles,
      setErrorMessage,
      setImagePreview,
      clearState
    );
  };

  const handleMultiFileUpload = async () => {
    if (information.size === 0) {
      setErrorMessage("Please choose atleast a file to add.");
      return;
    }
    setErrorMessage("");
    setUploadProgress();
    setUploadButtonClicked(true);
    handleMultipleFileUploadAjax(information);
  };

PHP endpoint to course of the a number of information add

upload-image.php

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    strive {
        if (isset($_FILES['file'])) {
            $uploadDirectory = __DIR__ . '/uploads/';
            if (!file_exists($uploadDirectory)) {
                mkdir($uploadDirectory, 0777, true);
            }

            $file = $_FILES['file'];

            $fileExtension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
            $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif'];

            if (in_array($fileExtension, $allowedExtensions)) {
                $newFilename = uniqid() . '.' . $fileExtension;
                $uploadPath = $uploadDirectory . $newFilename;

                if (move_uploaded_file($file['tmp_name'], $uploadPath)) {
                    echo json_encode(['message' => 'File uploaded successfully']);
                } else {
                    echo json_encode(['error' => 'Failed to move the file']);
                }
            } else {
                echo json_encode(['error' => 'File type not allowed']);
            }
        } else {
            echo json_encode(['error' => 'No file found in the request']);
        }
    } catch (Exception $e) {
        echo json_encode(['error' => $e->getMessage()]);
    }
} else {
    echo json_encode(['error' => 'Invalid request method']);
}


View demo Obtain

↑ Again to High

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments