Spring Boot React JS File Download Example

author : Sai K

In this tutorial, we will create a full-stack application using Spring Boot for the backend and React (using

functional components and hooks) for the frontend. We will implement user registration and login functionalities

using Spring Security 6+ and React 18. The tutorial will cover setting up the project, configuring Spring Security,

creating a Spring Boot REST API for user registration and login, and building a React application for the same.

We will also use Bootstrap for styling.


Prerequisites

Before we start, ensure you have the following:

  • Java Development Kit (JDK) installed

  • Apache Maven installed

  • Node.js and npm installed

  • An IDE (such as IntelliJ IDEA, Eclipse, or VS Code) installed

Step 1: Setting Up the Spring Boot Project

1.1 Create a Spring Boot Project

1. Open Spring Initializr:

  • Go to Spring Initializr in your web browser.

  • 2. Configure Project Metadata:

    • Project: Maven Project

    • Language: Java

    • Spring Boot: Select the latest version of Spring Boot 3

    • Group: com.example

    • Artifact: spring-boot-react-file-download

    • Name: spring-boot-react-file-download

    • Description:Full Stack Application with Spring Boot and React for File Download

    • Package Name:com.example.springbootreactfiledownload

    • Packaging: Jar

    • Java Version: 17 (or your preferred version)

    • Click Next.

    3. Select Dependencies:

  • On the Dependencies screen, select the dependencies you need
    • Spring Web

    • Spring Boot DevTools

  • Click Next.
  • 4. Generate the Project:

    • Click Generate to download the project zip file.

    • Extract the zip file to your desired location.

    5. Open the Project in Your IDE:

    • Open your IDE and import the project as a Maven project.

    1.2 Project Structures

    After importing the project, you will see the following structure in your IDE:

    
        spring-boot-react-auth
    ├── src
    │   ├── main
    │   │   ├── java
    │   │   │   └── com
    │   │   │       └── example
    │   │   │           └── springbootreactauth
    │   │   │               ├── SpringBootReactAuthApplication.java
    │   │   │               ├── config
    │   │   │               ├── controller
    │   │   │               ├── model
    │   │   │               ├── repository
    │   │   │               └── service
    │   ├── main
    │   │   └── resources
    │   │       ├── application.properties
    │   └── test
    │       └── java
    │           └── com
    │               └── example
    │                   └── springbootreactauth
    │                       └── SpringBootReactAuthApplicationTests.java
    └── pom.xml
    

    Step 2: Creating the Backend

    2.1 Create the File Download Service

    This service will handle retrieving the files from the server.

    In the service package, create a new Java class named FileDownloadService:

    
                        package com.example.springbootreactfiledownload.service;
    
    import org.springframework.core.io.Resource;
    import org.springframework.core.io.UrlResource;
    import org.springframework.stereotype.Service;
    
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    @Service
    public class FileDownloadService {
    
        private final Path fileStorageLocation = Paths.get("uploads").toAbsolutePath().normalize();
    
        public Resource loadFileAsResource(String fileName) {
            try {
                Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
                Resource resource = new UrlResource(filePath.toUri());
                if (resource.exists()) {
                    return resource;
                } else {
                    throw new RuntimeException("File not found " + fileName);
                }
            } catch (Exception ex) {
                throw new RuntimeException("File not found " + fileName, ex);
            }
        }
    
    }  

    Explanation:

    • Path Initialization: The fileStorageLocation is initialized to the "uploads" directory in the project root. This

      is where the files will be stored.

    • Load File Method: The loadFileAsResource method loads a file as a resource by its name. If the file

      exists, it returns the resource; otherwise, it throws an exception.

    2.2 Create the File Download Controller

    This controller will expose the REST API endpoint to handle file downloads.

    In the controller package, create a new Java class named FileDownloadController:

    
        package com.example.springbootreactfiledownload.controller;
    
    import com.example.springbootreactfiledownload.service.FileDownloadService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.io.Resource;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/api/files")
    public class FileDownloadController {
    
        private final FileDownloadService fileDownloadService;
    
        @Autowired
        public FileDownloadController(FileDownloadService fileDownloadService) {
            this.fileDownloadService = fileDownloadService;
        }
    
        @GetMapping("/download/{fileName:.+}")
        public ResponseEntity downloadFile(@PathVariable String fileName) {
            Resource resource = fileDownloadService.loadFileAsResource(fileName);
    
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                    .body(resource);
        }
    }
    

    Explanation:

    • File Download Endpoint: The /download/{fileName} endpoint handles GET requests to download files. It

      receives the file name as a path variable and loads the file as a resource using the FileDownloadService.

    • Response: It returns the file as an attachment in the response.

    2.3 Update application.properties

    Ensure the application.properties file is set up correctly:

    
        # File upload properties
    spring.servlet.multipart.max-file-size=2MB
    spring.servlet.multipart.max-request-size=2MB
    

    Step 3: Creating the Frontend with React

    3.1 Set Up React Project

    1.Open a terminal and navigate to your workspace directory.

    2.Create a new React project using Create React App:

    npx create-react-app react-frontend

    3.Navigate to the project directory:

    cd react-frontend

    3.2 Install Axios

    Install Axios to make HTTP requests:

    
        npm install axios
    

    3.3 Install Bootstrap

    Install Bootstrap for styling:

    npm install bootstrap

    3.4 Create Components

    Create the necessary components for the file download functionality.

    3.4.1 Create FileDownloadService.js

    Create a new file FileDownloadService.js in the src directory to handle API requests:

    
        import axios from 'axios';
    
    const API_BASE_URL = "http://localhost:8080/api/files";
    
    class FileDownloadService {
        downloadFile(fileName) {
            return axios.get(`${API_BASE_URL}/download/${fileName}`, {
                responseType: 'blob',
            });
        }
    }
    
    export default new FileDownloadService();
    

    Explanation:

    • API Base URL: The base URL for the API endpoints.

    • downloadFile Method:This method takes a file name as input and sends a GET request to the backend API

      to download the file.

    • 3.4.2 Create FileDownloadComponent.js

      Create a new file FileDownloadComponent.js in the src/components directory:

      
          import React, { useState } from 'react';
      import FileDownloadService from '../FileDownloadService';
      import 'bootstrap/dist/css/bootstrap.min.css';
      
      const FileDownloadComponent = () => {
          const [fileName, setFileName] = useState('');
          const [message, setMessage] = useState('');
      
          const handleFileChange = (e) => {
              setFileName(e.target.value);
          };
      
          const handleFileDownload = async (e) => {
              e.preventDefault();
              try {
                  const response = await FileDownloadService.downloadFile(fileName);
                  const url = window.URL.createObjectURL(new Blob([response.data]));
                  const link = document.createElement('a');
                  link.href = url;
                  link.setAttribute('download', fileName);
                  document.body.appendChild(link);
                  link.click();
                  setMessage('File downloaded successfully!');
              } catch (error) {
                  setMessage('File download failed!');
              }
          };
      
          return (
              < div className="container mt-5">
                  < div className="row justify-content-center">
                      < div className="col-md-6">
                          < div className="card">
                              < div className="card-header">File Download< /div>
                              < div className="card-body">
                                  {message && < div className="alert alert-info">{message}< /div>}
                                  < form onSubmit={handleFileDownload}>
                                      < div className="form-group">
                                          < label>Enter file name< /label>
                                          < input
                                              type="text"
                                              className="form-control"
                                              value={fileName}
                                              onChange={handleFileChange}
                                          />
                                      < /div>
                                      < button type="submit" className="btn btn-primary mt-3
      
      ">Download< /button>
                                  < /form>
                              < /div>
                          < /div>
                      < /div>
                  < /div>
              < /div>
          );
      };
      
      export default FileDownloadComponent;
      

      Explanation:

      • File Name Input: The handleFileChange method sets the file name to the component's state when a file

        name is entered.

      • File Download: The handleFileDownload method sends the file name to the backend API using

        FileDownloadService and handles the response or error messages. If the download is successful, it creates

        a link to download the file and triggers a click event to download it.

      • UI: The component renders a form with an input for the file name and a submit button. It displays

        messages based on the file download result.

      3.4.3 Create App.js

      Modify the App.js file to include the file download component:

      
      import React from 'react';
      import FileDownloadComponent from './components/FileDownloadComponent';
      import 'bootstrap/dist/css/bootstrap.min.css';
      
      const App = () => {
          return (
              < div className="container">
                  < FileDownloadComponent />
              < /div>
          );
      };
      
      export default App;
      

      3.4.4 Update index.js

      Ensure the index.js file is set up correctly:

      
          import React from 'react';
      import ReactDOM from 'react-dom/client';
      import './index.css';
      import App from './App';
      import 'bootstrap/dist/css/bootstrap.min.css';
      
      const root = ReactDOM.createRoot(document.getElementById('root'));
      root.render(
          < React.StrictMode>
              < App />
          < /React.StrictMode>
      );
      

      Step 4: Running the Application

      4.1 Run the Spring Boot Application

      1.Open the SpringBootReactFileDownloadApplication class in the src/main/java/com/example/springbootreactfiledownload directory.

      Click the green Run button in your IDE or use the terminal to run the application:

      ./mvnw spring-boot:run

      4.2 Run the React Application

      1.Open a terminal and navigate to the react-frontend directory.

      2.Start the React application:

      npm start

      3.Open your web browser and navigate to http://localhost:3000.

      You can now use the file download functionality provided by the React frontend and Spring Boot backend.

      Conclusion

      In this tutorial, we created a full-stack application using Spring Boot for the backend and React (with functional

      components and hooks) for the frontend. We implemented a file download functionality and created a simple file

      download form with React. This setup provides a solid foundation for developing more complex full-stack

      applications with file download capabilities.


      Related Spring and Spring Boot Tutorials/Guides: