This article demonstrates how to implement a REST API in Java using Spring Boot to serve a ZIP file and how to download it from a ReactJS frontend with full example.
1. Backend (Java + Spring Boot)
1.1 Project Setup
Add the necessary dependencies to your pom.xml
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
1.2 Create a ZIP File and Serve It
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@RestController
public class FileDownloadController {
@GetMapping("/api/download-zip")
public ResponseEntity<InputStreamResource> downloadZip() throws IOException {
// Create a temp file to hold the zip
Path tempZip = Files.createTempFile("example", ".zip");
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(tempZip))) {
// Add files into the zip (in-memory content for example)
zipOut.putNextEntry(new ZipEntry("hello.txt"));
zipOut.write("Hello from the ZIP file!".getBytes());
zipOut.closeEntry();
zipOut.putNextEntry(new ZipEntry("info.txt"));
zipOut.write("Some more information.".getBytes());
zipOut.closeEntry();
}
InputStreamResource resource = new InputStreamResource(new FileInputStream(tempZip.toFile()));
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=files.zip")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.contentLength(Files.size(tempZip))
.body(resource);
}
}
2. Frontend (ReactJS)
2.1 Axios Installation
Install Axios for making HTTP requests:
npm install axios
2.2 Download Button Component
import React from 'react';
import axios from 'axios';
const DownloadZip = () => {
const handleDownload = async () => {
try {
const response = await axios.get('http://localhost:8080/api/download-zip', {
responseType: 'blob'
});
// Create a URL for the blob
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'files.zip'); // Specify filename
document.body.appendChild(link);
link.click();
link.remove();
} catch (error) {
console.error('Download error:', error);
}
};
return (
<div>
<h2>Download ZIP File</h2>
<button onClick={handleDownload}>Download</button>
</div>
);
};
export default DownloadZip;
3. CORS Configuration (Optional)
If your frontend and backend are running on different ports, enable CORS in Spring Boot:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST");
}
};
}
}
4. Conclusion
You’ve now created a simple Spring Boot REST API to serve a ZIP file and a ReactJS frontend to download it. This pattern is useful for downloading reports, export files, or any dynamically generated content.