Spring Boot + Angular : File Upload, List, Download, and Delete Example


To implement file upload, list, download, and delete functionality using Angular 19 for the frontend and Spring Boot 3 for the backend, follow these updated steps:


1. Backend: Spring Boot 3

Dependencies

Add the required dependencies to your pom.xml file:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- File Upload and Apache Commons -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
    </dependency>
</dependencies>

File Controller

Create a FileController that handles file upload, list, download, and delete operations:

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.*;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/files")
public class FileController {

    private final Path uploadDir = Paths.get("uploads");

    public FileController() throws IOException {
        // Create the upload directory if it does not exist
        Files.createDirectories(uploadDir);
    }

    // Upload a file
    @PostMapping("/upload")
    public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            Path filePath = uploadDir.resolve(file.getOriginalFilename());
            Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
            return ResponseEntity.ok("File uploaded: " + file.getOriginalFilename());
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error uploading file");
        }
    }

    // List all files
    @GetMapping("/list")
    public ResponseEntity<List<String>> listFiles() {
        try {
            List<String> files = Files.list(uploadDir)
                    .map(path -> path.getFileName().toString())
                    .collect(Collectors.toList());
            return ResponseEntity.ok(files);
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    // Download a file
    @GetMapping("/download/{fileName}")
    public ResponseEntity<byte[]> downloadFile(@PathVariable String fileName) throws IOException {
        Path filePath = uploadDir.resolve(fileName);
        if (!Files.exists(filePath)) {
            return ResponseEntity.notFound().build();
        }

        byte[] fileContent = Files.readAllBytes(filePath);
        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
                .body(fileContent);
    }

    // Delete a file
    @DeleteMapping("/delete/{fileName}")
    public ResponseEntity<String> deleteFile(@PathVariable String fileName) {
        try {
            Path filePath = uploadDir.resolve(fileName);
            Files.deleteIfExists(filePath);
            return ResponseEntity.ok("File deleted: " + fileName);
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error deleting file");
        }
    }
}

CORS Configuration

Allow cross-origin requests to connect Angular with 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 CorsConfig {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("http://localhost:4200");
            }
        };
    }
}

2. Frontend: Angular 19

Setup Project

If you don’t have an Angular project yet, create one:

npm install -g @angular/cli
ng new file-manager
cd file-manager

Create File Service

Generate a service to handle HTTP requests:

ng generate service file

In file.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class FileService {
  private apiUrl = 'http://localhost:8080/api/files';

  constructor(private http: HttpClient) {}

  uploadFile(file: File): Observable<string> {
    const formData = new FormData();
    formData.append('file', file);
    return this.http.post(`${this.apiUrl}/upload`, formData, { responseType: 'text' });
  }

  listFiles(): Observable<string[]> {
    return this.http.get<string[]>(`${this.apiUrl}/list`);
  }

  downloadFile(fileName: string): Observable<Blob> {
    return this.http.get(`${this.apiUrl}/download/${fileName}`, { responseType: 'blob' });
  }

  deleteFile(fileName: string): Observable<string> {
    return this.http.delete(`${this.apiUrl}/delete/${fileName}`, { responseType: 'text' });
  }
}

Create File Component

Generate a component:

ng generate component file-manager

In file-manager.component.html:

<h2>File Manager</h2>

<!-- Upload File -->
<input type="file" (change)="onFileSelected($event)" />
<button (click)="uploadFile()">Upload</button>

<!-- List Files -->
<h3>File List</h3>
<ul>
  <li *ngFor="let file of fileList">
    {{ file }}
    <button (click)="downloadFile(file)">Download</button>
    <button (click)="deleteFile(file)">Delete</button>
  </li>
</ul>

In file-manager.component.ts:

import { Component, OnInit } from '@angular/core';
import { FileService } from '../file.service';

@Component({
  selector: 'app-file-manager',
  templateUrl: './file-manager.component.html',
})
export class FileManagerComponent implements OnInit {
  fileList: string[] = [];
  selectedFile: File | null = null;

  constructor(private fileService: FileService) {}

  ngOnInit(): void {
    this.fetchFiles();
  }

  onFileSelected(event: Event): void {
    const input = event.target as HTMLInputElement;
    if (input.files) {
      this.selectedFile = input.files[0];
    }
  }

  uploadFile(): void {
    if (this.selectedFile) {
      this.fileService.uploadFile(this.selectedFile).subscribe(() => {
        alert('File uploaded successfully');
        this.fetchFiles();
      });
    }
  }

  fetchFiles(): void {
    this.fileService.listFiles().subscribe((data) => {
      this.fileList = data;
    });
  }

  downloadFile(fileName: string): void {
    this.fileService.downloadFile(fileName).subscribe((blob) => {
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = fileName;
      a.click();
      window.URL.revokeObjectURL(url);
    });
  }

  deleteFile(fileName: string): void {
    this.fileService.deleteFile(fileName).subscribe(() => {
      alert('File deleted successfully');
      this.fetchFiles();
    });
  }
}

Import HttpClientModule

In app.module.ts, import HttpClientModule:

import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [AppComponent, FileManagerComponent],
  imports: [BrowserModule, HttpClientModule],
  bootstrap: [AppComponent],
})
export class AppModule {}

3. Run the Application

Backend:

Run Spring Boot:

mvn spring-boot:run

Frontend:

Run Angular:

ng serve

Access Application

Open http://localhost:4200 to use the file upload, list, download, and delete functionalities.


Summary

This setup includes:

  • Spring Boot 3 for backend API (file operations).
  • Angular 19 for the frontend UI.
  • Seamless communication between the frontend and backend using HTTP requests.

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete