Backend Development 16 min read

Six Practical File Upload and Download Solutions for Spring Boot

This article presents six commonly used file upload and download techniques for Spring Boot, covering basic Multipart handling, stream-based download, integration with Alibaba Cloud OSS and MinIO, as well as high‑concurrency chunked uploads with Nginx, each accompanied by complete code examples and usage scenarios.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Six Practical File Upload and Download Solutions for Spring Boot

File upload and download may seem trivial, but implementing them correctly in a large framework like Spring Boot can be challenging; improper handling can lead to lost files, slow uploads, or time‑outs that jeopardize a project.

1. Basic File Upload: Multipart + Spring Boot Controller

Applicable Scenario

Simple file upload without complex requirements, such as a standard form submission or API endpoint.

Code Example

@RestController
public class FileUploadController {
    // Spring Boot default file upload
    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file) throws IOException {
        // Get original file name
        String fileName = file.getOriginalFilename();
        // Define local storage path
        String savePath = "D:/uploads/" + fileName;
        // Save file locally
        File dest = new File(savePath);
        file.transferTo(dest);
        return "Upload successful! Saved path: " + savePath;
    }
}

Explanation

The code leverages Spring Boot's built‑in MultipartFile handling to store small files directly on the server with minimal configuration.

2. File Download: InputStream + OutputStream

Applicable Scenario

When you need to provide a download endpoint that controls streaming, supports large files, or applies custom headers.

Code Example

@GetMapping("/download")
public void downloadFile(HttpServletResponse response) throws IOException {
    String filePath = "D:/uploads/sample.txt";
    File file = new File(filePath);
    if (!file.exists()) {
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    response.setContentType("application/octet-stream");
    response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
    InputStream inputStream = new FileInputStream(file);
    OutputStream outputStream = response.getOutputStream();
    byte[] buffer = new byte[1024];
    int length;
    while ((length = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, length);
    }
    inputStream.close();
    outputStream.close();
}

Explanation

This implementation manually reads the file via InputStream and writes it to the HTTP response using OutputStream , giving precise control over the download process.

3. File Upload + OSS: Spring Boot Integration with Alibaba Cloud OSS

Applicable Scenario

Storing files in the cloud for large‑scale access and reducing server load.

Maven Dependency

com.aliyun
aliyun-sdk-oss
3.10.2

Code Example

@RestController
public class OssFileUploadController {
    @Value("${aliyun.oss.endpoint}") private String endpoint;
    @Value("${aliyun.oss.access-key-id}") private String accessKeyId;
    @Value("${aliyun.oss.access-key-secret}") private String accessKeySecret;
    @Value("${aliyun.oss.bucket-name}") private String bucketName;

    @PostMapping("/uploadToOss")
    public String uploadFileToOss(@RequestParam("file") MultipartFile file) {
        try {
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            String fileName = file.getOriginalFilename();
            InputStream inputStream = file.getInputStream();
            ossClient.putObject(bucketName, fileName, inputStream);
            ossClient.shutdown();
            return "File uploaded to OSS successfully! File name: " + fileName;
        } catch (Exception e) {
            e.printStackTrace();
            return "Upload failed: " + e.getMessage();
        }
    }
}

Explanation

The controller reads OSS configuration from properties, creates an OSSClient , and uploads the received file to the specified bucket.

4. File Download + OSS: Direct Download from OSS

Applicable Scenario

When files have already been stored in OSS and need to be served to clients without involving the application server's storage.

Code Example

@GetMapping("/downloadFromOss")
public void downloadFileFromOss(@RequestParam("fileName") String fileName, HttpServletResponse response) {
    try {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        OSSObject ossObject = ossClient.getObject(bucketName, fileName);
        InputStream inputStream = ossObject.getObjectContent();
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        OutputStream outputStream = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, length);
        }
        inputStream.close();
        outputStream.close();
        ossClient.shutdown();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Explanation

The method fetches the object from OSS, streams it directly to the HTTP response, and thus offloads storage responsibilities to the cloud.

5. File Upload + MinIO: Distributed Storage Solution

Applicable Scenario

When a self‑hosted, S3‑compatible storage is preferred over public cloud services.

Maven Dependency

io.minio
minio
8.0.3

Code Example

@RestController
public class MinioFileUploadController {
    @Value("${minio.url}") private String minioUrl;
    @Value("${minio.access-key}") private String accessKey;
    @Value("${minio.secret-key}") private String secretKey;
    @Value("${minio.bucket-name}") private String bucketName;

    @PostMapping("/uploadToMinio")
    public String uploadToMinio(@RequestParam("file") MultipartFile file) {
        try {
            MinioClient minioClient = MinioClient.builder()
                .endpoint(minioUrl)
                .credentials(accessKey, secretKey)
                .build();
            String fileName = file.getOriginalFilename();
            minioClient.putObject(
                PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build()
            );
            return "File uploaded to MinIO successfully, file name: " + fileName;
        } catch (Exception e) {
            e.printStackTrace();
            return "Upload failed: " + e.getMessage();
        }
    }
}

Explanation

MinIO uses the same S3‑compatible API as OSS; the code creates a MinioClient and stores the file in a private bucket.

6. High‑Concurrency File Upload: Spring Boot + Nginx + Chunked Upload

Applicable Scenario

Large files or many simultaneous uploads where a single request would time out; chunked uploading splits the file into smaller parts.

Front‑end JavaScript Example

// Front‑end chunked upload example
const uploadFile = (file) => {
    const chunkSize = 1024 * 1024; // 1 MB per chunk
    let start = 0;
    let end = chunkSize;
    const totalChunks = Math.ceil(file.size / chunkSize);
    const uploadNextChunk = () => {
        const formData = new FormData();
        formData.append('file', file.slice(start, end));
        fetch('/uploadChunk', {
            method: 'POST',
            body: formData
        }).then(response => {
            if (response.ok) {
                start = end;
                end = start + chunkSize;
                if (start < file.size) {
                    uploadNextChunk(); // recurse
                } else {
                    alert('File upload completed!');
                }
            } else {
                alert('Upload failed!');
            }
        });
    };
    uploadNextChunk(); // start uploading
};

Back‑end Spring Boot Chunk Handler

@RestController
public class FileUploadController {
    @PostMapping("/uploadChunk")
    public String uploadChunk(@RequestParam("file") MultipartFile file) {
        try {
            String fileName = "bigfile_part_" + System.currentTimeMillis();
            String savePath = "D:/uploads/" + fileName;
            File dest = new File(savePath);
            file.transferTo(dest);
            return "Chunk uploaded successfully: " + fileName;
        } catch (IOException e) {
            e.printStackTrace();
            return "Upload failed: " + e.getMessage();
        }
    }
}

Explanation

The front‑end slices the file and sends each chunk via fetch ; the back‑end stores each chunk locally. After all chunks are received, they can be merged into the final file, enabling reliable high‑throughput uploads.

Conclusion

The article covered six different file upload/download tools, ranging from basic local storage to cloud‑based OSS/MinIO solutions and high‑concurrency chunked uploads. For simple needs, Spring Boot's built‑in Multipart and OSS integration are sufficient; for more complex or large‑scale scenarios, MinIO or chunked uploads with Nginx provide greater control and scalability.

Regardless of project size, handling file transfer correctly is crucial to avoid later stability problems; the provided code snippets give a solid starting point for implementation.

Promotional note: If you are preparing for a Java interview, the site ddkk.com offers over 10,000 Java interview questions and a comprehensive set of tutorials for free.

JavaSpring BootFile Uploadfile downloadMinIOOSSChunked Upload
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.