Implementing File Storage and Email Dispatch in Spring Boot Applications

File Storage Implementation

This section details the configuration and controller logic required to accept multipart form data and persist uploaded documents to a local server directory using modern Java practices.

Dependencies and Configuration

Ensure your build environment utilizes JDK 8 or newer. The core Maven dependencies for web capabilities and template support include:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
</dependencies>

Configure the application.properties file to establish upload size limits and define the physical storage path. Using the modern Spring Boot property namespace ensures compatibility with current releases:

server.port=8080
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB
app.storage.directory=./server_uploads

Controller Logic

Spring's MultipartFile interface provides robust utilities for handling binary data. By leveraging the Java NIO API alongside Spring's built-in transfer methods, we can efficiently save files while automatically managing resource streams.

@RestController
@RequestMapping("/api/documents")
public class FileResourceController {

    @Value("${app.storage.directory}")
    private Path targetDirectory;

    @PostMapping("/ingest")
    public ResponseEntity<String> handleUpload(@RequestParam("attachment") MultipartFile rawData) {
        if (rawData.isEmpty()) {
            return ResponseEntity.badRequest().body("Request contains no file data.");
        }
        try {
            Path destinationPath = targetDirectory.resolve(rawData.getOriginalFilename());
            
            // Ensure the target directory exists before writing
            Files.createDirectories(destinationPath.getParent());
            
            // Efficiently copies the file to the destination path
            rawData.transferTo(destinationPath.toFile());
            return ResponseEntity.ok("Document successfully stored.");
        } catch (IOException exception) {
            return ResponseEntity.internalServerError().body("Storage operation failed: " + exception.getMessage());
        }
    }
}

Client Interface

For browser-based verification, a straightforward HTML form with multipart/form-data encoding is required. Developers can also utilize REST clients like Postman by setting the request body to form-data and maping the file key appropriately.

<form action="/api/documents/ingest" method="post" enctype="multipart/form-data">
    <label for="doc">Choose a file:</label>
    <input type="file" id="doc" name="attachment" required/>
    <button type="submit">Submit</button>
</form>

Email Dispatch Mechanism

Integrating SMTP protocols enables applications to trigger programmatic notifications. Spring Boot's mail starter abstracts the underlying JavaMail complexity, allowing developers to construct and transmit messages with minimal boilerplate.

SMTP Configuration

Include the mail starter in your pom.xml alongside the context support module. Subsequently, define the SMTP server details in the properties file. For major providers, generate an application-specific authorization code to replace your standard account password.

spring.mail.host=smtp.provider.com
spring.mail.port=587
spring.mail.username=admin@provider.com
spring.mail.password=your_generated_auth_code
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

Message Construction and Delivery

We define a Data Transfer Object (DTO) to encapsulate email metadata and a controller utilizing constructor injection to manage various message types, including plain text, file attachments, and dynamically templated HTML.

@RestController
@RequestMapping("/communications")
public class NotificationController {

    private final JavaMailSender transport;
    private final TemplateEngine renderer;

    public NotificationController(JavaMailSender transport, TemplateEngine renderer) {
        this.transport = transport;
        this.renderer = renderer;
    }

    @PostMapping("/dispatch/basic")
    public String sendPlainText(@RequestBody EmailPayload payload) {
        SimpleMailMessage msg = new SimpleMailMessage();
        msg.setFrom(payload.getOriginator());
        msg.setTo(payload.getDestination());
        msg.setSubject(payload.getSubjectLine());
        msg.setText(payload.getMessageBody());
        
        transport.send(msg);
        return "Notification dispatched successfully.";
    }

    @PostMapping("/dispatch/attached")
    public String sendWithAttachment(@RequestBody EmailPayload payload) throws MessagingException {
        MimeMessage complexMsg = transport.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(complexMsg, true);
        
        helper.setFrom(payload.getOriginator());
        helper.setTo(payload.getDestination());
        helper.setSubject(payload.getSubjectLine());
        helper.setText(payload.getMessageBody());

        // Embed a local file as an attachment
        FileSystemResource doc = new FileSystemResource(new File("reports/monthly.pdf"));
        helper.addAttachment("Monthly_Report.pdf", doc);
        
        transport.send(complexMsg);
        return "Message with attachment delivered.";
    }

    @PostMapping("/dispatch/templated")
    public String sendHtmlTemplate(@RequestBody EmailPayload payload) throws Exception {
        MimeMessage msg = transport.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(msg, true);
        
        helper.setFrom(payload.getOriginator());
        helper.setTo(payload.getDestination());
        helper.setSubject(payload.getSubjectLine());

        // Populate template variables
        Context ctx = new Context();
        ctx.setVariable("recipientName", payload.getDestination());
        ctx.setVariable("activationCode", "X99Z2");
        
        String htmlContent = renderer.process("onboarding_template", ctx);
        helper.setText(htmlContent, true);

        transport.send(msg);
        return "Templated email sent.";
    }
}

// Data Transfer Object
public class EmailPayload {
    private String originator;
    private String destination;
    private String subjectLine;
    private String messageBody;
    // Standard getters and setters apply here
}

Endpoint Verification

Utilize a REST client to issue a POST request to /communications/dispatch/basic using the following JSON structure:

{
  "originator": "system@app.com",
  "destination": "user@example.com",
  "subjectLine": "Security Alert",
  "messageBody": "Unrecognized login attempt detected from new device."
}

Upon successful execution, the API returns a confirmation string, and the recipient's inbox is updated accordingly. For inline images, utilize addInline instead of attachments and reference the Content ID within the HTML markup.

Tags: spring-boot java file-upload smtp thymeleaf

Posted on Wed, 28 Oct 2026 16:04:18 +0000 by javawizkid