Creating a Spring Boot file upload service with progress tracking

File uploads appear in profile systems, claims portals, document management tools and online shops. A Spring Boot service can accept multipart requests while a browser displays useful progress feedback, giving users confidence when sending large files over an NBN connection or mobile network.

The key design choice is where progress is measured. Browser-side tracking shows bytes sent from the client, while server-side tracking confirms how many bytes the application has received and stored. For Australian users in Sydney, Melbourne, Brisbane or regional areas, this distinction matters because connection speeds and latency can vary considerably.

Choose a tracking strategy

A simple upload service uses an HTTP POST endpoint and reports progress through the browser’s upload events. This approach has low complexity and works well when a user needs immediate visual feedback rather than a durable background job.

Approach Best use Strength Limitation
Browser upload events Standard web forms Easy and responsive Does not confirm permanent storage
Polling an upload status endpoint Large or asynchronous files Survives page changes Requires status persistence
WebSocket or SSE updates Dashboards and batch jobs Near real-time server updates Adds infrastructure
Resumable uploads Unreliable or very large transfers Can continue after interruption More implementation effort

For a customer portal serving both metropolitan and regional Australia, browser events are a sensible starting point. Add server-side status records when uploads may take several minutes, require virus scanning, or are processed by a queue.

Configure Spring Boot for multipart uploads

Spring Boot enables multipart handling through MultipartFile. Set practical limits in application.yml rather than accepting the defaults blindly:

spring:
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 110MB
      file-size-threshold: 2MB

The endpoint can receive the file and return a generated identifier. Never use the original filename as the storage path, because filenames may contain path traversal characters or collide with existing files.

@PostMapping("/api/files")
public ResponseEntity<FileReceipt> upload(@RequestParam MultipartFile file)
        throws IOException {
    String id = UUID.randomUUID().toString();
    Path target = uploadRoot.resolve(id).normalize();

    Files.copy(file.getInputStream(), target,
               StandardCopyOption.REPLACE_EXISTING);

    return ResponseEntity.ok(new FileReceipt(id, file.getSize()));
}

In a production service, store metadata such as the owner, content type, size, checksum and upload state in PostgreSQL or another database. The file itself may belong in Amazon S3, Azure Blob Storage or an Australian-hosted object storage service.

Display client-side upload progress

The browser’s XMLHttpRequest API exposes an upload.progress event. This reports the number of bytes transmitted and lets the interface update a progress bar without repeatedly contacting the server.

const request = new XMLHttpRequest();
const formData = new FormData();
formData.append("file", fileInput.files[0]);

request.upload.addEventListener("progress", event => {
  if (event.lengthComputable) {
    const percentage = Math.round(event.loaded * 100 / event.total);
    progressBar.value = percentage;
    status.textContent = `${percentage}% uploaded`;
  }
});

request.addEventListener("load", () => {
  status.textContent = request.status === 200
    ? "Upload complete"
    : "Upload failed";
});

request.open("POST", "/api/files");
request.send(formData);

This percentage describes network transmission, not virus scanning, database persistence or cloud replication. Clear wording such as “Uploading” and “Processing” prevents users from closing the page too early.

Make large uploads reliable

A reverse proxy can reject a request before Spring Boot receives it. Nginx, for example, may require an appropriate client_max_body_size value. Container platforms and API gateways can impose their own timeout and request-size restrictions.

For larger files, write to temporary storage and move the file only after validation succeeds. Avoid loading the entire content into memory. On variable NBN services or mobile connections around regional Queensland, a dropped connection can waste a long transfer, so resumable chunk uploads may be worthwhile.

Useful reliability measures include:

Validate content and protect users

Do not trust the extension or the browser-provided MIME type. Inspect file signatures where possible, restrict permitted formats and enforce per-user quotas. A PDF upload should be checked as a PDF rather than accepted merely because its name ends in .pdf.

Files should be stored outside the publicly served application directory, with access controlled through authenticated download endpoints. For systems handling identity documents, follow the Australian Privacy Act and consider OAIC expectations around collection, retention and disclosure. Data residency requirements may also influence whether a Sydney region or another Australian hosting location is selected.

Important safeguards include:

Add server-side status for background processing

If the service scans, converts or extracts data from a file, return 202 Accepted with an upload ID instead of keeping the request open. A client can call /api/files/{id}/status periodically, or subscribe through Server-Sent Events for a live dashboard.

A status response might contain:

{
  "id": "8f4d...",
  "state": "PROCESSING",
  "receivedBytes": 73400320,
  "totalBytes": 104857600,
  "percentage": 70
}

For accurate server progress, wrap the input stream or update counters while copying data to storage. Publish those counters through Redis, a database or an application event system. Browser progress remains useful, but server status becomes the authoritative result after the request finishes.

Test and operate the service

Test more than a successful small upload. Include oversized files, empty files, duplicate names, interrupted transfers and unauthorised downloads. Test from Australian mobile networks and regional connections as well as office broadband, since latency can expose timeout and retry problems.

Operational checks should include:

A well-designed Spring Boot upload service separates transmission, storage, validation and processing. That separation makes progress reporting clearer, keeps sensitive files protected and gives the system room to grow from a small local application into a dependable service for Australian customers.