📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.
✅ Some premium posts are free to read — no account needed. Follow me on Medium to stay updated and support my writing.
🎓 Top 10 Udemy Courses (Huge Discount): Explore My Udemy Courses — Learn through real-time, project-based development.
▶️ Subscribe to My YouTube Channel (172K+ subscribers): Java Guides on YouTube
The source code of this tutorial available on my GitHub Repository.
1. Tools and Technologies Used
- Spring Boot - 3
- Hibernate - 6
- JDK - 17 or later
- Spring Framework - 6
- Maven - 3.2+
- IDE - Eclipse or Spring Tool Suite (STS)
- Database - MySQL
2. Create a Spring Boot Application
3. Packaging Structure
4. Maven Dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
5. Configuring the Database and Multipart File properties
spring.datasource.url= jdbc:mysql://localhost:3306/springboot_demo?useSSL=false
spring.datasource.username= root
spring.datasource.password= root
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto = update
## Hibernate Logging
logging.level.org.hibernate.SQL= DEBUG
## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=200MB
# Max Request Size
spring.servlet.multipart.max-request-size=215MB
6. Create JPA Entity - DatabaseFile
package net.javaguides.springboot.fileuploaddownload.model;
import org.hibernate.annotations.GenericGenerator;
import jakarta.persistence.*;
@Entity
@Table(name = "files")
public class DatabaseFile {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
private String fileName;
private String fileType;
@Lob
private byte[] data;
public DatabaseFile() {
}
public DatabaseFile(String fileName, String fileType, byte[] data) {
this.fileName = fileName;
this.fileType = fileType;
this.data = data;
}
public String getId() {
return id;
}
public String getFileName() {
return fileName;
}
public String getFileType() {
return fileType;
}
public byte[] getData() {
return data;
}
public void setId(String id) {
this.id = id;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
public void setData(byte[] data) {
this.data = data;
}
}
7. Create a Spring Data Repository - DatabaseFileRepository.java
package net.javaguides.springboot.fileuploaddownload.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import net.javaguides.springboot.fileuploaddownload.model.DatabaseFile;
@Repository
public interface DatabaseFileRepository extends JpaRepository<DatabaseFile, String> {
}
8. Service Layer - DatabaseFileService
package net.javaguides.springboot.fileuploaddownload.service;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import net.javaguides.springboot.fileuploaddownload.exception.FileNotFoundException;
import net.javaguides.springboot.fileuploaddownload.exception.FileStorageException;
import net.javaguides.springboot.fileuploaddownload.model.DatabaseFile;
import net.javaguides.springboot.fileuploaddownload.repository.DatabaseFileRepository;
@Service
public class DatabaseFileService {
@Autowired
private DatabaseFileRepository dbFileRepository;
public DatabaseFile storeFile(MultipartFile file) {
// Normalize file name
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {
// Check if the file's name contains invalid characters
if (fileName.contains("..")) {
throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
}
DatabaseFile dbFile = new DatabaseFile(fileName, file.getContentType(), file.getBytes());
return dbFileRepository.save(dbFile);
} catch (IOException ex) {
throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
}
}
public DatabaseFile getFile(String fileId) {
return dbFileRepository.findById(fileId)
.orElseThrow(() - > new FileNotFoundException("File not found with id " + fileId));
}
}
9. Writing APIs for File Upload and Download
Build File Upload Rest API
package net.javaguides.springboot.fileuploaddownload.controller;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import net.javaguides.springboot.fileuploaddownload.model.DatabaseFile;
import net.javaguides.springboot.fileuploaddownload.payload.Response;
import net.javaguides.springboot.fileuploaddownload.service.DatabaseFileService;
@RestController
public class FileUploadController {
@Autowired
private DatabaseFileService fileStorageService;
@PostMapping("/uploadFile")
public Response uploadFile(@RequestParam("file") MultipartFile file) {
DatabaseFile fileName = fileStorageService.storeFile(file);
String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/downloadFile/")
.path(fileName.getFileName())
.toUriString();
return new Response(fileName.getFileName(), fileDownloadUri,
file.getContentType(), file.getSize());
}
@PostMapping("/uploadMultipleFiles")
public List < Response > uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
return Arrays.asList(files)
.stream()
.map(file -> uploadFile(file))
.collect(Collectors.toList());
}
}
Build File Download Rest API
package net.javaguides.springboot.fileuploaddownload.controller;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import net.javaguides.springboot.fileuploaddownload.model.DatabaseFile;
import net.javaguides.springboot.fileuploaddownload.service.DatabaseFileService;
@RestController
public class FileDownloadController {
@Autowired
private DatabaseFileService fileStorageService;
@GetMapping("/downloadFile/{fileName:.+}")
public ResponseEntity < Resource > downloadFile(@PathVariable String fileName, HttpServletRequest request) {
// Load file as Resource
DatabaseFile databaseFile = fileStorageService.getFile(fileName);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(databaseFile.getFileType()))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + databaseFile.getFileName() + "\"")
.body(new ByteArrayResource(databaseFile.getData()));
}
}
10. Payloads - Response.java
package net.javaguides.springboot.fileuploaddownload.payload;
public class Response {
private String fileName;
private String fileDownloadUri;
private String fileType;
private long size;
public Response(String fileName, String fileDownloadUri, String fileType, long size) {
this.fileName = fileName;
this.fileDownloadUri = fileDownloadUri;
this.fileType = fileType;
this.size = size;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileDownloadUri() {
return fileDownloadUri;
}
public void setFileDownloadUri(String fileDownloadUri) {
this.fileDownloadUri = fileDownloadUri;
}
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
}
11. Custom Exception Classes
FileNotFoundException
package net.javaguides.springboot.fileuploaddownload.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND)
public class FileNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1 L;
public FileNotFoundException(String message) {
super(message);
}
public FileNotFoundException(String message, Throwable cause) {
super(message, cause);
}
}
FileStorageException
package net.javaguides.springboot.fileuploaddownload.exception;
public class FileStorageException extends RuntimeException {
private static final long serialVersionUID = 1 L;
public FileStorageException(String message) {
super(message);
}
public FileStorageException(String message, Throwable cause) {
super(message, cause);
}
}
package net.javaguides.springboot.fileuploaddownload.exception;
public class FileStorageException extends RuntimeException {
private static final long serialVersionUID = 1 L;
public FileStorageException(String message) {
super(message);
}
public FileStorageException(String message, Throwable cause) {
super(message, cause);
}
}
11. Running the Application and Testing the APIs via Postman
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootUploadDownloadFileApplication {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
mvn spring-boot:run
Firstly Thanks for this Tutto, it's very impotant but i like to know why when i upload a file type pdf i have an error : com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'data' at row 1
ReplyDeleteGreat Job !!
ReplyDelete
ReplyDeleteCan I see the database table query statement?
all are okey, but when i am uploading my image using phone then you only saving url of image when i have to display somewhere that image then how I would be able to display, how can we get image in actually?
ReplyDeleteHey why does is said "Required request part 'file' is not present". How do I fix this Mr.Ramesh
ReplyDelete