DEV Community

loizenai
loizenai

Posted on

Angular 11 + SpringBoot Upload/Download MultipartFile

https://grokonez.com/angular-11-springboot-upload-download-multipartfile

When uploading files to Servlet containers, application needs to register a MultipartConfigElement class. But Spring Boot makes thing more easy by configuring it automatically. In this tutorial, we're gonna look at way to build an Angular 11 App Client to upload/get MultipartFile to/from Spring Boot RestApi Server.

Related posts:

I. Technologies

  • Angular 11
  • Java 1.8
  • Spring Boot 2.0.3.RELEASE
  • Maven 3.3.9
  • Spring Tool Suite 3.9.0.RELEASE

    II. Overview

    1. Spring Boot Server

    angular-6-upload-multipart-files-spring-boot-server-project-structure-server

  • StorageService helps to init, delete all files, store file, load file

  • UploadController uses StorageService to provide Rest API: POST a file, GET all files

  • application.properties to configure parameters such as MultipartFile max size...

  • Spring Boot Starter Web dependency in pom.xml

    2. Angular 11 App Client

    angular-6-upload-multipart-files-spring-boot-server-project-structure-client

  • upload-file.service provides methods: push File to Storage and get Files.

  • list-upload.component gets and displays list of Files.

  • form-upload.component helps upload File.

  • details-upload.component is detail for each item in list of Files.

angular-6-upload-multipart-file-spring-boot-angular-overview

III. Practice

1. Spring Boot Server

1.1 Create Spring Boot project

With Dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

1.2 Create Storage Service for File Systems

Create StorageService with 4 functions:

  • public void store(MultipartFile file): save a file
  • public Resource loadFile(String filename): load a file
  • public void deleteAll(): remove all uploaded files
  • public void init(): create upload directory

storage/StorageService.java


package com.javasampleapproach.spring.uploadfiles.storage;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;

@Service
public class StorageService {

    Logger log = LoggerFactory.getLogger(this.getClass().getName());
    private final Path rootLocation = Paths.get("upload-dir");

    public void store(MultipartFile file) {
        try {
            Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename()));
        } catch (Exception e) {
            throw new RuntimeException("FAIL!");
        }
    }

    public Resource loadFile(String filename) {
        try {
            Path file = rootLocation.resolve(filename);
            Resource resource = new UrlResource(file.toUri());
            if (resource.exists() || resource.isReadable()) {
                return resource;
            } else {
                throw new RuntimeException("FAIL!");
            }
        } catch (MalformedURLException e) {
            throw new RuntimeException("FAIL!");
        }
    }

    public void deleteAll() {
        FileSystemUtils.deleteRecursively(rootLocation.toFile());
    }

    public void init() {
        try {
            Files.createDirectory(rootLocation);
        } catch (IOException e) {
            throw new RuntimeException("Could not initialize storage!");
        }
    }
}

1.3 Create Upload Controller

controller/UploadController.java


package com.javasampleapproach.spring.uploadfiles.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;

import com.javasampleapproach.spring.uploadfiles.storage.StorageService;

@Controller
public class UploadController {

    @Autowired
    StorageService storageService;

    List files = new ArrayList();

    @PostMapping("/post")
    public ResponseEntity handleFileUpload(@RequestParam("file") MultipartFile file) {
        String message = "";
        try {
            storageService.store(file);
            files.add(file.getOriginalFilename());

            message = "You successfully uploaded " + file.getOriginalFilename() + "!";
            return ResponseEntity.status(HttpStatus.OK).body(message);
        } catch (Exception e) {
            message = "FAIL to upload " + file.getOriginalFilename() + "!";
            return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(message);
        }
    }

    @GetMapping("/getallfiles")
    public ResponseEntity> getListFiles(Model model) {
        List fileNames = files
                .stream().map(fileName -> MvcUriComponentsBuilder
                        .fromMethodName(UploadController.class, "getFile", fileName).build().toString())
                .collect(Collectors.toList());

        return ResponseEntity.ok().body(fileNames);
    }

    @GetMapping("/files/{filename:.+}")
    @ResponseBody
    public ResponseEntity getFile(@PathVariable String filename) {
        Resource file = storageService.loadFile(filename);
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"")
                .body(file);
    }
}

1.4 Config multipart

Open application.properties:


spring.servlet.multipart.max-file-size=500KB
spring.servlet.multipart.max-request-size=500KB
  • spring.servlet.multipart.max-file-size: limit total file size for each request.
  • spring.servlet.multipart.max-request-size: limit total request size for a multipart/form-data.

    1.5 Init Storage for File System

    SpringBootUploadFileApplication.java
    
    package com.javasampleapproach.spring.uploadfiles;

import javax.annotation.Resource;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.javasampleapproach.spring.uploadfiles.storage.StorageService;

@SpringBootApplication
public class SpringBootFileUploadApplication implements CommandLineRunner {

@Resource
StorageService storageService;

public static void main(String[] args) {
    SpringApplication.run(SpringBootFileUploadApplication.class, args);
}

@Override
public void run(String... arg) throws Exception {
    storageService.deleteAll();
    storageService.init();
}
Enter fullscreen mode Exit fullscreen mode

}

2. Angular 11 App Client

2.0 Generate Service & Components

Run commands below:

  • ng g s upload/UploadFile
  • ng g c upload/FormUpload
  • ng g c upload/ListUpload
  • ng g c upload/DetailsUpload On each Component selector, delete app- prefix, then change tslint.json rules - "component-selector" to false.

    2.1 App Module

    app.module.ts
    
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';
import { DetailsUploadComponent } from './upload/details-upload/details-upload.component';
import { FormUploadComponent } from './upload/form-upload/form-upload.component';
import { ListUploadComponent } from './upload/list-upload/list-upload.component';

@NgModule({
declarations: [
AppComponent,
DetailsUploadComponent,
FormUploadComponent,
ListUploadComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

2.2 Upload File Service

upload/upload-file.service.ts


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

@Injectable({
  providedIn: 'root'
})
export class UploadFileService {

  constructor(private http: HttpClient) { }

  pushFileToStorage(file: File): Observable> {
    const formdata: FormData = new FormData();

    formdata.append('file', file);

    const req = new HttpRequest('POST', '/post', formdata, {
      reportProgress: true,
      responseType: 'text'
    });

    return this.http.request(req);
  }

  getFiles(): Observable {
    return this.http.get('/getallfiles');
  }
}

https://grokonez.com/angular-11-springboot-upload-download-multipartfile

Discussion (0)