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:
- Spring Web
- Spring Boot DevTools
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:
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.