> ## Documentation Index
> Fetch the complete documentation index at: https://docs.markpdf.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Spring Boot

> Controller in Spring Boot (Java/Kotlin) to convert documents.

# Spring Boot

## Controller

```java theme={null}
// ConvertController.java
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.util.Map;

@RestController
public class ConvertController {

    @Value("${flash-md.api-url}")
    private String apiUrl;

    @Value("${flash-md.api-key}")
    private String apiKey;

    private final RestTemplate rest = new RestTemplate();

    @PostMapping("/api/convert")
    public ResponseEntity<String> convert(@RequestParam("file") MultipartFile file) throws Exception {
        HttpHeaders headers = new HttpHeaders();
        headers.set("x-api-key", apiKey);
        headers.setContentType(MediaType.parseMediaType(
            file.getContentType() != null ? file.getContentType() : "application/octet-stream"
        ));

        String url = apiUrl + "/convert/raw?filename=" + file.getOriginalFilename() + "&mode=fast";
        HttpEntity<byte[]> entity = new HttpEntity<>(file.getBytes(), headers);

        ResponseEntity<String> res = rest.exchange(url, HttpMethod.POST, entity, String.class);

        if (res.getStatusCode().value() == 200) {
            return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType("text/markdown; charset=utf-8"))
                .body(res.getBody());
        }

        if (res.getStatusCode().value() == 202) {
            @SuppressWarnings("unchecked")
            Map<String, Object> job = rest.postForObject(url, entity, Map.class);
            String markdown = pollJob((String) job.get("job_id"));
            return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType("text/markdown; charset=utf-8"))
                .body(markdown);
        }

        return ResponseEntity.status(res.getStatusCode()).body(res.getBody());
    }

    private String pollJob(String jobId) throws InterruptedException {
        HttpHeaders h = new HttpHeaders();
        h.set("x-api-key", apiKey);
        HttpEntity<Void> req = new HttpEntity<>(h);

        while (true) {
            Thread.sleep(5000);

            @SuppressWarnings("unchecked")
            ResponseEntity<Map> res = rest.exchange(
                apiUrl + "/jobs/" + jobId, HttpMethod.GET, req, Map.class
            );
            Map<String, Object> data = res.getBody();

            if ("completed".equals(data.get("status"))) {
                return (String) data.get("body");
            }
            if ("failed".equals(data.get("status"))) {
                throw new RuntimeException("Job failed: " + data.get("error"));
            }
        }
    }
}
```

## application.properties

```properties theme={null}
flash-md.api-url=https://api.markpdf.tech
flash-md.api-key=${FLASH_MD_API_KEY}
spring.servlet.multipart.max-file-size=12MB
```
