The following method returns the entire file to the client. The client application has to indicate its own indeterminate loading status, as the client browser will not be aware of the progress of the download.

    public ResponseEntity<Resource> downloadAttachmentOld(@PathVariable Long id) throws IOException {
        log.debug("Download report called for id {}", id);

        Optional<Attachment> attachment = attachmentRepository.findById(id);


            Resource resource = new UrlResource(Paths.get(attachment.get().getPath()).toUri());

            if (resource.exists() && resource.isReadable()) {
                String contentDisposition = String.format("attachment; filename=\"%s\"", resource.getFile().getName());

                String mimeType = mimeDetectionService.getMimeType(resource.getFile());

                return ResponseEntity.ok()
                        .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
                        .header(HttpHeaders.CONTENT_TYPE, mimeType)

        log.warn("Returning report not found");
        return ResponseEntity.notFound().build();

mimeDectionService is simply a service that invokes a method from Apache Tika

public class MimeDetectionService {

    private final Tika tika = new Tika();

    public String getMimeType(File file) {
        try {
            return tika.detect(file);
        } catch (IOException e) {
            return "application/octet-stream";