Spring Boot Vue.js File Upload and Download Example
author : Sai K
In this tutorial, we will create a full-stack application using Spring Boot 3 for the backend and
Vue.js 3.4 for the
front end. The application will include functionalities for uploading and
downloading files.
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
Go to Spring Initializr in your web browser.
2.Configure Project Metadata:
- Project: Maven Project
- Language: Java
- Spring Boot: Select the latest version of Spring Boot 3
- Group: com.example
- Artifact: file-upload-download
- Name:file-upload-download
- Description: File Upload and Download Application with Spring Boot and Vue.js
- Package Name:com.example.fileuploaddownload
- Packaging: Jar
- Java Version: 17 (or your preferred version)
- Click Next.
3.Select Dependencies:
- Spring Web
- Spring Boot DevTools
4.Generate the Project:
- Click Generate to download the project zip file.
- Extract the zip file to your desired location.
5.Open the Project in Your IDE:
- Open your IDE and import the project as a Maven project.
1.2 Update application.properties
Open the application.properties file located in the src/main/resources directory and add the
following
configuration:
# File storage location
file.upload-dir=uploads
1.3 Create a File Storage Service
In the com.example.fileuploaddownload.service package, create a new Java class named FileStorageService:
package com.example.fileuploaddownload.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
@Service
public class FileStorageService {
private final Path fileStorageLocation;
public FileStorageService(@Value("${file.upload-dir}") String uploadDir) {
this.fileStorageLocation = Paths.get(uploadDir)
.toAbsolutePath().normalize();
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception ex) {
throw new RuntimeException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
public String storeFile(MultipartFile file) {
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {
if (fileName.contains("..")) {
throw new RuntimeException("Invalid path sequence " + fileName);
}
Path targetLocation = this.fileStorageLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return fileName;
} catch (IOException ex) {
throw new RuntimeException("Could not store file " + fileName + ". Please try again!", ex);
}
}
public Path loadFileAsResource(String fileName) {
return this.fileStorageLocation.resolve(fileName).normalize();
}
}
1.4 Create the FileController Class
In the com.example.fileuploaddownload.controller package, create a new Java class named FileController:
package com.example.fileuploaddownload.controller;
import com.example.fileuploaddownload.service.FileStorageService;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.nio.file.Path;
@RestController
@RequestMapping("/api/files")
public class FileController {
private final FileStorageService fileStorageService;
public FileController(FileStorageService fileStorageService) {
this.fileStorageService = fileStorageService;
}
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {
return fileStorageService.storeFile(file);
}
@GetMapping("/download/{fileName:.+}")
public ResponseEntity downloadFile(@PathVariable String fileName) {
Path filePath = fileStorageService.loadFileAsResource(fileName);
Resource resource;
try {
resource = new UrlResource(filePath.toUri());
if (!resource.exists()) {
throw new RuntimeException("File not found " + fileName);
}
} catch (Exception e) {
throw new RuntimeException("File not found " + fileName, e);
}
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
}
Step 2: Creating the Frontend with Vue.js
2.1 Set Up Vue Project
1.Open a terminal and navigate to your workspace directory.
2. Create a new Vue project using Vue CLI:
Open a terminal and navigate to your workspace directory.
Create a new Vue project using Vue CLI:
3.Navigate to the project directory:
cd vue-frontend
2.2 Install Axios and Bootstrap
Install Axios to make HTTP requests and Bootstrap for styling:
npm install axios bootstrap
2.3 Create Components
Create the necessary components for file upload and download.
2.3.1 Create FileService.js
Create a new file FileService.js in the src directory to handle API requests for file upload and download:
import axios from 'axios';
const API_BASE_URL = "http://localhost:8080/api/files";
class FileService {
uploadFile(file) {
let formData = new FormData();
formData.append("file", file);
return axios.post(`${API_BASE_URL}/upload`, formData, {
headers: {
"Content-Type": "multipart/form-data"
}
});
}
downloadFile(fileName) {
return axios.get(`${API_BASE_URL}/download/${fileName}`, {
responseType: 'blob'
});
}
}
export default new FileService();
2.3.2 Create UploadComponent.vue
Create a new file UploadComponent.vue in the src/components directory:
<template>
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">Upload File</div>
<div class="card-body">
<form @submit.prevent="uploadFile">
<div class="form-group">
<input type="file" @change="selectFile" class="form-control" />
</div>
<button type="submit" class="btn btn-primary mt-3">Upload</button>
</form>
<div v-if="fileName" class="mt-3">
<span>Uploaded file: {{ fileName }}</span>
<button @click="downloadFile" class="btn btn-secondary ml-3">Download</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import FileService from '../FileService';
export default {
data() {
return {
selectedFile: null,
fileName: ''
};
},
methods: {
selectFile(event) {
this.selectedFile = event.target.files[0];
},
uploadFile() {
FileService.uploadFile(this.selectedFile).then(response => {
this.fileName = response.data;
});
},
downloadFile() {
FileService.downloadFile(this.fileName).then(response => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', this.fileName);
document.body.appendChild(link);
link.click();
});
}
}
};
</script>
2.3.3 Create App.vue
Modify the App.vue file to include the UploadComponent:
<template>
<div id="app">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">File Upload and Download</a>
</nav>
<upload-component></upload-component>
</div>
</template>
<script>
import UploadComponent from './components/UploadComponent.vue';
export default {
name: 'App',
components: {
UploadComponent
}
};
</script>
<style>
nav {
margin-bottom: 20px;
}
</style>
2.3.4 Update main.js
Ensure the main.js file is set up correctly:
import { createApp } from 'vue';
import App
from './App.vue';
import 'bootstrap/dist/css/bootstrap.min.css';
createApp(App).mount('#app');
Step 3: Running the Application
3.1 Run the Spring Boot Application
1. Open the FileUploadDownloadApplication class in the src/main/java/com/example/fileuploaddownload
directory.
2.Click the green Run button in your IDE or use the terminal to run the application:
./mvnw spring-boot:run
3.2 Run the Vue.js Application
1.Open a terminal and navigate to the vue-frontend directory.
2. Start the Vue application:
npm run serve
3.Open your web browser and navigate to http://localhost:8080.
You should now be able to upload and download files using the Vue.js frontend and Spring Boot backend.
Conclusion
In this tutorial, we created a full-stack application using Spring Boot for the backend and Vue.js
for the frontend.
We implemented file upload and download functionalities and handled the
necessary configurations to connect
the two parts of the application. This setup provides a
solid foundation for developing more complex full-stack
applications.