Пример Download file c Spring Boot

View more Tutorials:

1- Цель статьи

В данной статье я покажу вам как создать приложение  Spring Boot с фуркциями для скачивания файлов с  Web Server на локальный компьютер. Например файлы изображений, zip, pdf,...
Ниже являются некоторые способы для создания функции скачивания файла:
  1. ResponseEntity<InputStreamResource>: Написать метод возвращающий объект ResponseEntity, данный объект обертывает (wrap) объект InputStreamResource (Это данные файла, которые скачаны пользователем).
  2. ResponseEntity<ByteArrayResource>: Написать метод возвращающий объект ResponseEntity, данный объект обертывает (wrap) объект ByteArrayResource (Это данные файла, которые скачаны пользователем).
  3. HttpServletRespone: Написать напрямую данные файла, которые нужно скачать в HttpServletRespone.
Для файлов большого размера, при скачивании пользователю понадобится подождать определенное время. Вам нужно предоставить некоторую информацию для браузера:

Content-Disposition

Content-Disposition: Это информация на части  Header у Response, она показывает содержание которое планируется для отображения на браузере.
  • inline: содержание отобразится автоматически.
  • attachment: Прикрепленный файл.
  • form-data: Данные form.
  • ....
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="java-tutorial.pdf"

Content-Length

contentLength: Это размер содержания (Считается по единице  byte). Данная информация помогает браузеру оповестить пользователю размер содержания, которое готовится для скачивания. Поэтому при скачивании браузер может оповестить пользователя количество уже скачанных  byte, отображая процент, который уже скачался, рассчитывая оставшееся время.

Content-Type

Данная информация помогает браузеру узнать с помощью какого приложения можно открыть данное содержание, и подсказывает пользователю открыть с помощью существующего приложения на их компьютере при завершении скачивания. Установить  Content-Type=application/octet-stream, если вы хотите, чтобы ваш браузер скачал содержание сразу же, не спрашивая пользователя.
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="picture.png"


Content-Type: image/png
Content-Disposition: attachment; filename="picture.png"


Content-Type: image/png
Content-Disposition: inline; filename="picture.png"
See more:

2- Создать проект Spring Boot

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.o7planning</groupId>
    <artifactId>SpringBootDownload</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>SpringBootDownload</name>
    <description>Spring Boot +Download Example</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
SpringBootDownloadApplication.java
package org.o7planning.sbdownload;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootDownloadApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDownloadApplication.class, args);
    }
    
}

3- ResponseEntity

Написать метод, возвращающий объект  ResponseEntity, данный объект обертывает (wrap) объект InputStreamResource (Это данные файла, который скачал пользователь).
Example1Controller.java
package org.o7planning.sbdownload.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletContext;

import org.o7planning.sbdownload.utils.MediaTypeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class Example1Controller {

    private static final String DIRECTORY = "C:/PDF";
    private static final String DEFAULT_FILE_NAME = "java-tutorial.pdf";

    @Autowired
    private ServletContext servletContext;

    // http://localhost:8080/download1?fileName=abc.zip
    // Using ResponseEntity<InputStreamResource>
    @RequestMapping("/download1")
    public ResponseEntity<InputStreamResource> downloadFile1(
            @RequestParam(defaultValue = DEFAULT_FILE_NAME) String fileName) throws IOException {

        MediaType mediaType = MediaTypeUtils.getMediaTypeForFileName(this.servletContext, fileName);
        System.out.println("fileName: " + fileName);
        System.out.println("mediaType: " + mediaType);

        File file = new File(DIRECTORY + "/" + fileName);
        InputStreamResource resource = new InputStreamResource(new FileInputStream(file));

        return ResponseEntity.ok()
                // Content-Disposition
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())
                // Content-Type
                .contentType(mediaType)
                // Contet-Length
                .contentLength(file.length()) //
                .body(resource);
    }

}
MediaTypeUtils.java
package org.o7planning.sbdownload.utils;

import javax.servlet.ServletContext;

import org.springframework.http.MediaType;

public class MediaTypeUtils {

    // abc.zip
    // abc.pdf,..
    public static MediaType getMediaTypeForFileName(ServletContext servletContext, String fileName) {
        // application/pdf
        // application/xml
        // image/gif, ...
        String mineType = servletContext.getMimeType(fileName);
        try {
            MediaType mediaType = MediaType.parseMediaType(mineType);
            return mediaType;
        } catch (Exception e) {
            return MediaType.APPLICATION_OCTET_STREAM;
        }
    }
    
}

4- ResponseEntity

Написать метод, возвращающий объект ResponseEntity, данный объект обертывает (wrap) объект​​​​​​​ ByteArrayResource (Это данные файла, который скачал пользователь).
Example2Controller.java
package org.o7planning.sbdownload.controller;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.servlet.ServletContext;

import org.o7planning.sbdownload.utils.MediaTypeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class Example2Controller {

    private static final String DIRECTORY = "C:/PDF";
    private static final String DEFAULT_FILE_NAME = "java-tutorial.pdf";

    @Autowired
    private ServletContext servletContext;

    // http://localhost:8080/download2?fileName=abc.zip
    // Using ResponseEntity<ByteArrayResource>
    @GetMapping("/download2")
    public ResponseEntity<ByteArrayResource> downloadFile2(
            @RequestParam(defaultValue = DEFAULT_FILE_NAME) String fileName) throws IOException {

        MediaType mediaType = MediaTypeUtils.getMediaTypeForFileName(this.servletContext, fileName);
        System.out.println("fileName: " + fileName);
        System.out.println("mediaType: " + mediaType);

        Path path = Paths.get(DIRECTORY + "/" + DEFAULT_FILE_NAME);
        byte[] data = Files.readAllBytes(path);
        ByteArrayResource resource = new ByteArrayResource(data);

        return ResponseEntity.ok()
                // Content-Disposition
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + path.getFileName().toString())
                // Content-Type
                .contentType(mediaType) //
                // Content-Lengh
                .contentLength(data.length) //
                .body(resource);
    }

}

5- HttpServletRespone

Написать напрямую данные файла, который нужно скачать в  HttpServletRespone.
Example3Controller.java
package org.o7planning.sbdownload.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;

import org.o7planning.sbdownload.utils.MediaTypeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class Example3Controller {

    private static final String DIRECTORY = "C:/PDF";
    private static final String DEFAULT_FILE_NAME = "java-tutorial.pdf";

    @Autowired
    private ServletContext servletContext;

    // http://localhost:8080/download3?fileName=abc.zip
    // Using HttpServletResponse
    @GetMapping("/download3")
    public void downloadFile3(HttpServletResponse resonse,
            @RequestParam(defaultValue = DEFAULT_FILE_NAME) String fileName) throws IOException {

        MediaType mediaType = MediaTypeUtils.getMediaTypeForFileName(this.servletContext, fileName);
        System.out.println("fileName: " + fileName);
        System.out.println("mediaType: " + mediaType);

        File file = new File(DIRECTORY + "/" + fileName);

        // Content-Type
        // application/pdf
        resonse.setContentType(mediaType.getType());

        // Content-Disposition
        resonse.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName());

        // Content-Length
        resonse.setContentLength((int) file.length());

        BufferedInputStream inStream = new BufferedInputStream(new FileInputStream(file));
        BufferedOutputStream outStream = new BufferedOutputStream(resonse.getOutputStream());

        byte[] buffer = new byte[1024];
        int bytesRead = 0;
        while ((bytesRead = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, bytesRead);
        }
        outStream.flush();
        inStream.close();
    }

}

View more Tutorials: