Загружать и скачивать файлы в программе Spring Boot

Spring Boot

Загрузка и загрузка файла Spring Boot

Загрузка и загрузка файлов — одна из наиболее часто используемых функций веб-приложений.В этой главе я буду использовать простой пример, чтобы объяснить, как загружать и скачивать файлы в Spring Boot. Прежде чем начать текст, давайте рассмотрим простой процесс загрузки и скачивания файлов через интеллект-карту:

文件上传与下载思维导图
Загрузка файла и загрузка интеллект-карты

1. Загрузка файла

Для загрузки файла параметр соответствующего метода загрузки в контроллере должен бытьMultipartFileобъект,MultipartFileОбъект может быть объектом-массивом или отдельным объектом. Если это объект-массив, может быть выполнена загрузка нескольких файлов; здесь мы демонстрируем только загрузку одного файла. Следующий код показывает базовую структуру метода загрузки файла:

@PostMapping(value = "/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseBody
public String fileUpload(@RequestParam("file") MultipartFile file) throws IOException {
	return null;
}

Далее мы используемFileOutputStreamОбъект записывает загруженный клиентом файл на диск и возвращает сообщение "Файл успешно загружен". Ниже приведен полный код для загрузки файла:

package com.ramostear.application.controller;

import com.ramostear.application.model.FileInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @author : ramostear
 * @date : 2019/3/8 0008-15:35
 */
@Controller
public class FileController {


    @Value ( "${file.upload.root.dir}" )
    String fileUploadRootDir;

    private static Map<String,FileInfo> fileRepository = new HashMap<>();

    @PostConstruct
    public void initFileRepository(){
        FileInfo file1 = new FileInfo ().setFileName ( "bg1.jpg" );
        FileInfo file2 = new FileInfo ().setFileName ( "bg2.jpg" );
        FileInfo file3 = new FileInfo ().setFileName ( "bg3.jpg" );
        fileRepository.put ( file1.getName (),file1 );
        fileRepository.put ( file2.getName (),file2 );
        fileRepository.put ( file3.getName (),file3 );
    }

@PostMapping(value = "/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseBody
public String fileUpload(@RequestParam("file") MultipartFile file) throws IOException {

        File convertFile = new File ( fileUploadRootDir+file.getOriginalFilename ());
        FileOutputStream fileOutputStream = new FileOutputStream ( convertFile );
        fileOutputStream.write ( file.getBytes () );
        fileOutputStream.close ();

        FileInfo fileInfo = new FileInfo()
                .setFileName ( file.getOriginalFilename());

        fileRepository.put ( fileInfo.getName (),fileInfo);

        return "File is upload successfully";
    }
}

fileRepositoryИндексная информация для хранения загруженных файлов.

2. Загрузка файла

В приложении Spring Boot мы можем использоватьInputStreamResourceобъект для загрузки файла, в методе загрузки файла нам нужно установить соответствующие свойства объекта HttpHeander через Response, такие какContent-Disposition,Cache-Control,PragmaиExpiresи другие свойства. Кроме того, вам также необходимо указать тип ответа Response. Следующий код дает подробную информацию о загрузке файла:

@GetMapping("/download/{fileName}")
@ResponseBody
public ResponseEntity<Object> downloadFile(@PathVariable(name = "fileName") String fileName) throws FileNotFoundException {

        File file = new File ( fileUploadRootDir+fileName);
        InputStreamResource resource = new InputStreamResource ( new FileInputStream ( file ) );

        HttpHeaders headers = new HttpHeaders();
        headers.add ( "Content-Disposition",String.format("attachment;filename=\"%s",fileName));
        headers.add ( "Cache-Control","no-cache,no-store,must-revalidate" );
        headers.add ( "Pragma","no-cache" );
        headers.add ( "Expires","0" );

        ResponseEntity<Object> responseEntity = ResponseEntity.ok()
                .headers ( headers )
                .contentLength ( file.length ())
                .contentType(MediaType.parseMediaType ( "application/txt" ))
                .body(resource);

        return responseEntity;
    }

3. Список кодов

3.1 Контроллер загрузки и загрузки файлов

Ниже приведен код для полной загрузки и скачивания файла:

package com.ramostear.application.controller;

import com.ramostear.application.model.FileInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @author : ramostear
 * @date : 2019/3/8 0008-15:35
 */
@Controller
public class FileController {


    @Value ( "${file.upload.root.dir}" )
    String fileUploadRootDir;

    private static Map<String,FileInfo> fileRepository = new HashMap<>();

    @PostConstruct
    public void initFileRepository(){
        FileInfo file1 = new FileInfo ().setFileName ( "bg1.jpg" );
        FileInfo file2 = new FileInfo ().setFileName ( "bg2.jpg" );
        FileInfo file3 = new FileInfo ().setFileName ( "bg3.jpg" );
        fileRepository.put ( file1.getName (),file1 );
        fileRepository.put ( file2.getName (),file2 );
        fileRepository.put ( file3.getName (),file3 );
    }

    @GetMapping("/files")
    public String files(Model model){
        Collection<FileInfo> files = fileRepository.values ();
        model.addAttribute ( "data",files );
        return "files";
    }


    @PostMapping(value = "/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ResponseBody
    public String fileUpload(@RequestParam("file") MultipartFile file) throws IOException {

        File convertFile = new File ( fileUploadRootDir+file.getOriginalFilename ());
        FileOutputStream fileOutputStream = new FileOutputStream ( convertFile );
        fileOutputStream.write ( file.getBytes () );
        fileOutputStream.close ();

        FileInfo fileInfo = new FileInfo()
                .setFileName ( file.getOriginalFilename());

        fileRepository.put ( fileInfo.getName (),fileInfo);

        return "File is upload successfully";
    }

    @GetMapping("/download/{fileName}")
    @ResponseBody
    public ResponseEntity<Object> downloadFile(@PathVariable(name = "fileName") String fileName) throws FileNotFoundException {

        File file = new File ( fileUploadRootDir+fileName);
        InputStreamResource resource = new InputStreamResource ( new FileInputStream ( file ) );

        HttpHeaders headers = new HttpHeaders();
        headers.add ( "Content-Disposition",String.format("attachment;filename=\"%s",fileName));
        headers.add ( "Cache-Control","no-cache,no-store,must-revalidate" );
        headers.add ( "Pragma","no-cache" );
        headers.add ( "Expires","0" );

        ResponseEntity<Object> responseEntity = ResponseEntity.ok()
                .headers ( headers )
                .contentLength ( file.length ())
                .contentType(MediaType.parseMediaType ( "application/txt" ))
                .body(resource);

        return responseEntity;
    }



}

3.2 Модель данных

Создайте модель данных файловой информации в качестве носителя для загрузки файловой информации.Ниже приведен код FileInfo.java:

package com.ramostear.application.model;

import lombok.Data;

import java.util.Date;

/**
 * @author : ramostear
 * @date  : 2019/3/8 0008-15:25
 */
@Data
public class FileInfo {

    private String name;
    private Date uploadTime = new Date();

    public FileInfo setFileName(String name){
        this.setName ( name );
        return this;
    }

}

3.3 Файлы сборки Maven

Ниже приведен список конфигурации файла 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>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.ramostear</groupId>
	<artifactId>file-handling</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>file-handling</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

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

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</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>

Примечание. В этом случае в качестве шаблона представления используется механизм шаблонов freemarker.

3.4 Файл конфигурации

Файл application.properties в основном устанавливаетfreemarkerи пользовательский атрибут **file.upload.root.dir**:

spring.freemarker.cache=false
spring.freemarker.prefix=
spring.freemarker.suffix=.html
spring.freemarker.enabled=true
spring.freemarker.charset=UTF-8
spring.freemarker.template-loader-path=classpath:/templates/
file.upload.root.dir = C:/work/upload/

file.upload.root.dirПользовательский атрибут задает каталог для загрузки файлов:C:/work/upload/

3.5 Просмотры

В файле просмотра создается форма формы для загрузки файлов, а также создается список загруженных файлов для обеспечения операций загрузки файлов.

Форма загрузки файла:

上传文件form表单
загрузить форму файла

Список загрузки файлов:

文件下载列表
список загрузки файлов

Описание: файл загружается с использованием метода асинхронной загрузки, и форма не отправляется синхронно.

Код асинхронной операции загрузки файла выглядит следующим образом:

$("#upload").on("click",function () {
           var fileObj = document.getElementById("file").files[0];
           var form = new FormData();
           form.append("file",fileObj);
           var xhr = new XMLHttpRequest();
           xhr.open("post","http://localhost:8080/upload",true);
           xhr.onload = function(event){
               alert(event.currentTarget.responseText);
               window.location.href = window.location.href;
           };
           xhr.send(form);
        });

4. Упакуйте и запустите

Используйте команду Maven для упаковки приложения, следующая команда пакета maven:

mvn clean install

Запустите приведенную выше команду в окне консоли и подождите, пока maven упакует. Если в консоли отображается сообщение «BUILD SUCCESS», вы можете найти соответствующий файл JAR в целевой папке текущего каталога проекта.

Теперь вы можете запустить файл JAR с помощью следующей команды:

java -jar YOUR_JARFILE_NAME

После успешного запуска JAR-файла в окне консоли можно увидеть следующую информацию:

控制台窗口信息
информация об окне консоли

5. Тест

Откройте браузер и введите в адресной строке:http://localhost:8080/files. Ниже скриншот браузера после успешного запроса:

文件列表
список документов

Далее нажмите на любой изdownloadкнопку, чтобы проверить, нормально ли работает функция загрузки файла:

下载文件
Загрузка файла

Наконец, мы проверяем, нормально ли работает функция загрузки файлов. Перед тестированием давайте посмотрим на информацию о файле, хранящуюся в каталоге загрузки файлов:

文件上传目录
директория для загрузки файлов

Далее выбираем файл для загрузки и нажимаемuploadкнопка для загрузки файлов:

上传文件
загрузить файлы

На этом этапе файл и загрузка выполнены успешно, мы снова смотрим информацию о файле в каталоге загрузки файлов, чтобы убедиться, что файл успешно записан на диск:

文件上传目录对比
Сравнение каталогов загрузки файлов

6. Аксессуары

Весь исходный код этой главы был загружен в репозиторий кода Github, вы можете посетить следующий адрес, чтобы получить весь исходный код:GitHub.com/Слеза Рамоса/S…

Автор: Тан Чаохун, оригинальный текст:Загружать и скачивать файлы в программе Spring Boot