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
-
Open Spring Initializr:
- Go to Spring Initializr in your web browser.
-
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
.
-
Select Dependencies:
- On the
Dependencies
screen, select the dependencies you need:- Spring Web
- Spring Boot DevTools
- Click
Next
.
- On the
-
Generate the Project:
- Click
Generate
to download the project zip file. - Extract the zip file to your desired location.
- Click
-
Open the Project in Your IDE:
- Open your IDE and import the project as a Maven project.
1.2 Project Structure
After importing the project, you will see the following structure in your IDE:
spring-boot-react-file-download
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── springbootreactfiledownload
│ │ │ ├── SpringBootReactFileDownloadApplication.java
│ │ │ ├── controller
│ │ │ └── service
│ ├── main
│ │ └── resources
│ │ ├── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── springbootreactfiledownload
│ └── SpringBootReactFileDownloadApplicationTests.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<Resource> 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 handlesGET
requests to download files. It receives the file name as a path variable and loads the file as a resource using theFileDownloadService
. - 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
-
Open a terminal and navigate to your workspace directory.
-
Create a new React project using Create React App:
npx create-react-app react-frontend
-
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 usingFileDownloadService
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
- Open the
SpringBootReactFileDownloadApplication
class in thesrc/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
-
Open a terminal and navigate to the
react-frontend
directory. -
Start the React application:
npm start
-
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.
Comments
Post a Comment
Leave Comment