개발기술/Web Dev

Static File Upload

bsh6226 2025. 4. 12. 17:47

Generalized Static File Upload Workflow

Client uploads a file (MultipartFile)

  • Client (frontend or mobile) sends a multipart/form-data request:
POST /upload
Content-Type: multipart/form-data

--boundary
Content-Disposition: form-data; name="file"; filename="image.jpg"
Content-Type: image/jpeg

    (binary data)

 

Server stores the file (locally or in cloud) and returns a public-accessible URL

@PostMapping("/upload")
public String uploadImage(@RequestParam("file") MultipartFile file) throws IOException {
    String filename = UUID.randomUUID() + "_" + file.getOriginalFilename();
    Path uploadPath = Paths.get("uploads").resolve(filename);
    Files.copy(file.getInputStream(), uploadPath);
    return "/images/" + filename; // ← URL that client can later use
}

 

Client sends another API request with resource URL

POST /createPost
{
    "title": "Trip to Busan",
    "imageUrl": "/images/abc123_image.jpg"
}

 

 

 

Client references the file via URL in future requests

Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/images/**")
            .addResourceLocations("file:uploads/"); // ← absolute or relative path
    }
}

 

 

Two Common Approaches to Static File Uploading

🔁 1. Server-side Uploading (Traditional)

Client → Web Server → Storage Server (e.g., S3, File Server)

  • Client uploads the file to your web backend
  • Web server saves the file to disk or forwards it to a storage server/cloud
  • Then it returns the URL to the client

✅ Pros:

  • Easy to control/validate file content
  • Centralized logging, security

❌ Cons:

  • Web server handles heavy I/O load
  • Not scalable for large files or high frequency

2. Client-side Direct Uploading (Modern)

Client → Storage Server (e.g., S3, CDN)
→ Then Client → Web Server (with the URL)

  • Web server gives the client a "pre-signed URL" or upload destination
  • Client directly uploads the file to S3, Google Cloud, or file server
  • Then client tells the web server:
    "Hey! Here's the file URL I just uploaded"

✅ Pros:

  • Offloads storage I/O burden from web server
  • Ideal for large files or many users
  • Faster user experience

❌ Cons:

  • Slightly more complex (requires pre-signed URL logic or CORS config)
  • Must trust client-uploaded URLs (validate origin!)

 

 

orphaned file

Client uploads a file (e.g., image) → gets the URL
❌ But fails to send the URL to your backend (e.g., due to network error, user cancel, crash)

Result?

  • File is stored in your cloud (e.g., S3)
  • But the backend never knows about it
  • You now have an orphaned file sitting there, unused and untracked

 

Common Solutions

1. Use Pre-signed URLs with Expiry

  • You generate a temporary upload URL (e.g., valid for 5 minutes)
  • If the client doesn’t register the URL in time, the uploaded file:
    • May expire from a special temp bucket
    • Or gets marked for cleanup

2. Delayed file finalization

  • Uploads go to a temporary location
  • Only upon successful registration (second request), move file to "final" location
  • This way, only registered files are made persistent or public

3. Backend cleanup jobs (or lifecycle rules)

  • Periodically run a scheduled job or use S3 lifecycle rules:
    • Delete files older than X minutes that are not referenced in DB
    • You may tag files with pending=true and remove those that never got confirmed