This guide will walk you through creating a full-stack application with Spring Boot backend and Vue.js frontend for file management operations.
Backend (Spring Boot)
1. Create Spring Boot Project
Use Spring Initializr (https://start.spring.io/) with these dependencies:
- Spring Web
- Spring Data JPA
- H2 Database (or your preferred database)
2. File Entity
@Entity
public class FileEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String fileName;
private String fileType;
@Lob
private byte[] data;
// Constructors, getters, and setters
}
3. File Repository
public interface FileRepository extends JpaRepository<FileEntity, Long> {
}
4. File Service
@Service
public class FileStorageService {
@Autowired
private FileRepository fileRepository;
public FileEntity store(MultipartFile file) throws IOException {
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
FileEntity fileEntity = new FileEntity();
fileEntity.setFileName(fileName);
fileEntity.setFileType(file.getContentType());
fileEntity.setData(file.getBytes());
return fileRepository.save(fileEntity);
}
public FileEntity getFile(Long id) {
return fileRepository.findById(id)
.orElseThrow(() -> new RuntimeException("File not found with id " + id));
}
public List<FileEntity> getAllFiles() {
return fileRepository.findAll();
}
public void deleteFile(Long id) {
fileRepository.deleteById(id);
}
}
5. File Controller
@RestController
@RequestMapping("/api/files")
@CrossOrigin(origins = "http://localhost:8081") // Vue.js default port
public class FileController {
@Autowired
private FileStorageService storageService;
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
try {
storageService.store(file);
return ResponseEntity.ok("File uploaded successfully: " + file.getOriginalFilename());
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED)
.body("Could not upload the file: " + file.getOriginalFilename() + "!");
}
}
@GetMapping
public ResponseEntity<List<FileEntity>> getListFiles() {
List<FileEntity> files = storageService.getAllFiles();
return ResponseEntity.ok(files);
}
@GetMapping("/{id}")
public ResponseEntity<byte[]> getFile(@PathVariable Long id) {
FileEntity fileEntity = storageService.getFile(id);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + fileEntity.getFileName() + "\"")
.body(fileEntity.getData());
}
@DeleteMapping("/{id}")
public ResponseEntity<String> deleteFile(@PathVariable Long id) {
try {
storageService.deleteFile(id);
return ResponseEntity.ok("File deleted successfully!");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED)
.body("Could not delete the file!");
}
}
}
Frontend (Vue.js)
1. Create Vue.js Project
vue create file-upload-frontend
cd file-upload-frontend
npm install axios vue-axios
2. File Service (src/services/FileService.js)
import axios from 'axios';
const API_URL = 'http://localhost:8080/api/files';
class FileService {
upload(file) {
let formData = new FormData();
formData.append("file", file);
return axios.post(API_URL + "/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
}
getFiles() {
return axios.get(API_URL);
}
downloadFile(id) {
return axios.get(API_URL + `/${id}`, { responseType: 'blob' });
}
deleteFile(id) {
return axios.delete(API_URL + `/${id}`);
}
}
export default new FileService();
3. File List Component (src/components/FileList.vue)
<template>
<div>
<h2>File List</h2>
<table class="table">
<thead>
<tr>
<th>File Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="file in files" :key="file.id">
<td>{{ file.fileName }}</td>
<td>
<button @click="downloadFile(file.id)" class="btn btn-primary">Download</button>
<button @click="deleteFile(file.id)" class="btn btn-danger">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import FileService from '../services/FileService';
export default {
name: 'FileList',
data() {
return {
files: []
};
},
methods: {
getFiles() {
FileService.getFiles().then(response => {
this.files = response.data;
});
},
downloadFile(id) {
FileService.downloadFile(id).then(response => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', this.files.find(f => f.id === id).fileName);
document.body.appendChild(link);
link.click();
});
},
deleteFile(id) {
if (confirm('Are you sure you want to delete this file?')) {
FileService.deleteFile(id).then(() => {
this.getFiles();
});
}
}
},
mounted() {
this.getFiles();
}
};
</script>
4. File Upload Component (src/components/FileUpload.vue)
<template>
<div>
<h2>Upload File</h2>
<div>
<input type="file" ref="file" @change="handleFileUpload" />
<button @click="submitFile" class="btn btn-success">Upload</button>
</div>
<div v-if="message" class="alert alert-info mt-3">{{ message }}</div>
</div>
</template>
<script>
import FileService from '../services/FileService';
export default {
name: 'FileUpload',
data() {
return {
file: null,
message: ''
};
},
methods: {
handleFileUpload() {
this.file = this.$refs.file.files[0];
},
submitFile() {
if (!this.file) {
this.message = 'Please select a file first!';
return;
}
FileService.upload(this.file)
.then(() => {
this.message = 'File uploaded successfully!';
this.$refs.file.value = '';
this.$emit('file-uploaded');
})
.catch(() => {
this.message = 'Failed to upload file!';
});
}
}
};
</script>
5. App Component (src/App.vue)
<template>
<div id="app" class="container mt-5">
<h1>File Management System</h1>
<FileUpload @file-uploaded="refreshList" />
<FileList ref="fileList" />
</div>
</template>
<script>
import FileUpload from './components/FileUpload.vue';
import FileList from './components/FileList.vue';
export default {
name: 'App',
components: {
FileUpload,
FileList
},
methods: {
refreshList() {
this.$refs.fileList.getFiles();
}
}
};
</script>
<style>
.container {
max-width: 800px;
}
</style>
Running the Application
- Start the Spring Boot application
- In another terminal, start the Vue.js application:
npm run serve
Key Features
- File Upload: Select a file and upload it to the server
- File List: View all uploaded files in a table
- File Download: Download any file from the server
- File Delete: Remove files from the server