File Upload & Download as Multipart File using Angular + Spring Boot

Chinthaka Jayatilake
LinkIT
Published in
4 min readOct 8, 2019
Photo by Clay Banks on Unsplash

We know that when creating applications in the present day, it has become a requirement in most of them to upload and download files. But we know that with the security features in the browsers it is not as simple as in the past to upload and download files. We also need to look at the efficiency of the process as it is a main non-functional requirement nowadays.

So let us now create our Angular project.

ng new project_name

Let us create a simple HTML form first to get the file input and to show the downloaded file. In order to code it, we will move to the app.component.html file.

<h1>Upload and Download File</h1><input type="file" id="customFile" (change)="selectFile($event)"><button class="btn btn-primary" [disabled]="!selectedFiles || admincheck || status" (click)="upload()">Save File</button><button class="btn btn-primary" style="margin-left: 10px" (click)="downloadFile()">View File</button>

Next, we need to create a service to send the file as a multipart file to the back-end. We will be using this service in our app.component.ts file to communicate with the back-end.

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 https: HttpClient) { } pushFileToStorage(file: File): Observable<HttpEvent<{}>> { const data: FormData = new FormData(); data.append('file', file); const newRequest = new HttpRequest('POST', 'http://localhost:8080/savefile', data, {
reportProgress: true,
responseType: 'text'
});
return this.https.request(newRequest);}}

As the service is created now we can move to implement our app.component.ts file. Here we will be importing the service and with the use of it, we will be sending the file to the back-end. There are other few methods as well in the app.component.ts file to download the file, to check whether the selected file is the same and also to confirm whether a file has been selected.

import { Component } from '@angular/core';
import { HttpResponse, HttpEventType } from '@angular/common/http';
import { UploadFileService } from './Services/upload-file.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent { title = 'File-Upload-Save'; selectedFiles: FileList; currentFileUpload: File; progress: { percentage: number } = { percentage: 0 }; selectedFile = null; changeImage = false; constructor(private uploadService: UploadFileService){} downloadFile(){ const link = document.createElement('a');
link.setAttribute('target', '_blank');
link.setAttribute('href', '_File_Saved_Path');
link.setAttribute('download', 'file_name.pdf');
document.body.appendChild(link);
link.click();
link.remove();
} change($event) {
this.changeImage = true;
}
changedImage(event) {
this.selectedFile = event.target.files[0];
}
upload() { this.progress.percentage = 0;
this.currentFileUpload = this.selectedFiles.item(0);
this.uploadService.pushFileToStorage(this.currentFileUpload).subscribe(event => {
if (event.type === HttpEventType.UploadProgress) {
this.progress.percentage = Math.round(100 * event.loaded / event.total);
} else if (event instanceof HttpResponse) {
alert('File Successfully Uploaded');
}
this.selectedFiles = undefined;
}
);
}
selectFile(event) {
this.selectedFiles = event.target.files;
}
}

It is important to make sure that all the imports which are mentioned at the beginning of the component.ts files are present in the project node modules folder. If not they must be installed as below.

npm install imported_file_name

Now let us create the Spring Boot project. The below link will help you create your project easily.

Now let us add the below dependencies to our pom.xml file so that we could use them in our project by importing them.

<dependencies>

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

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

</dependencies>

Now let us create a class and write the method to collect the multipart file passed from the front-end and to convert it back to the original file format and save it in a given location.

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

@CrossOrigin(origins = "http://localhost:4200")
@Controller
public class FileUploader {

List<String> files = new ArrayList<String>();
private final Path rootLocation = Paths.get("_Path_To_Save_The_File");

@PostMapping("/savefile")
public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) {
String message;
try {
try {
Files.copy(file.getInputStream(), this.rootLocation.resolve("file_name.pdf"));
} catch (Exception e) {
throw new RuntimeException("FAIL!");
}
files.add(file.getOriginalFilename());

message = "Successfully uploaded!";
return ResponseEntity.status(HttpStatus.OK).body(message);
} catch (Exception e) {
message = "Failed to upload!";
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(message);
}
}
}

So that is it. A very simple application to store and retrieve files. It can be created in a few minutes. Why wait now. Let us check whether this works.

Feel free to add this module to your project when required and even implement it further according to your requirements. I hope you got something out of this.

The project source code can be viewed and downloaded from GitHub.

Cheers!! Have a pleasant day!!

Visit my Official Blog Site to send in your queries directly to me and to read more articles by me…

--

--