Spring Boot demo学习之上传文件

背景

最近在学习Spring Boot,跟着官方demo学习仍是会遇到很多坑,写个文章记录下,以便往后查阅。html

核心功能

使用@Controller注解声明接受请求,调用@Autowired自动注入的servcie来保存上传的文件,同时提供文件下载功能。spring

使用thymeleaf模板来处理html页面请求。
用@ConfigurationProperties注解来声明属性,配置文件存放目录。app

核心代码

控制层

在控制器中@Controller注解来代表这是一个控制层bean,能够接受http请求;
使用@Autowired注解来自动注入service类,用来执行对文件的操做;
分别使用@GetMapping和@PostMapping来接受GET、POST方法;
经过 return "uploadForm"; 的样子,交给模板引擎thymeleaf去处理,返回template目录下的uploadForm.html文件,并“注入”响应的属性 如files、message等。ide

@Controller // 控制器注解
public class FileUploadController {
    private final StorageService storageService; // 下面自动注入

    @Autowired
    public FileUploadController(StorageService storageService) {
        this.storageService = storageService;
    }

    @GetMapping("/")
    public String listUploadedFiles(Model model) throws IOException {

        model.addAttribute("files", storageService.loadAll().map(
                path -> MvcUriComponentsBuilder.fromMethodName(FileUploadController.class,
                        "serveFile", path.getFileName().toString()).build().toString())
                .collect(Collectors.toList()));

        return "uploadForm"; // 由模板引擎负责返回 uploadForm.html,在template目录下。
    }

    @GetMapping("/files/{filename:.+}") // 下载文件
    @ResponseBody
    public ResponseEntity<Resource> serveFile(@PathVariable String filename) {

        Resource file = storageService.loadAsResource(filename);
        return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"" + file.getFilename() + "\"").body(file);
    }

    @PostMapping("/")
    public String handleFileUpload(@RequestParam("file") MultipartFile file,
                                   RedirectAttributes redirectAttributes) {

        storageService.store(file);
        redirectAttributes.addFlashAttribute("message",
                "You successfully uploaded " + file.getOriginalFilename() + "!");

        return "redirect:/"; // 跳转到 get的请求里(上面的listUploadedFiles方法)
    }

}

服务层

这个类主要用来执行一些文件处理操做,没什么特殊的,spring-boot

比较坑的是,由于用到配置属性,仅仅用Autowired来注入仍是不行的, 还必须使用 @EnableConfigurationProperties(StorageProperties.class) 来声明配置属性类,这个比较坑。。学习

@Service //声明service
@EnableConfigurationProperties(StorageProperties.class) // 容许使用配置注解
public class FileSystemStorageService implements StorageService {

    private final Path rootLocation;

    @Autowired // 自动注入
    public FileSystemStorageService(StorageProperties properties) {
        this.rootLocation = Paths.get(properties.getLocation());
    }

属性配置

使用@ConfigurationProperties声明这是一个属性配置类,参数声明顶级命名空间。ui

比较坑的是, 须要在pom.xml里引入如下依赖:this

<dependency>
            <groupId> org.springframework.boot </groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional> true </optional>
        </dependency>

而后就能够正常使用了。。。code

@ConfigurationProperties("storage")
public class StorageProperties {

    /**
     * Folder location for storing files
     */
    private String location = "upload-dir";

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

}

以上配置完成后,能够在application.properties 文件里添加 storage.location = myFiles来指明文件存储路径。。。orm

其它坑

在学习的过程当中可能会出现 “Re-run spring boot configuration annotation”的错误,这个就是由于在service中只用Autowired去自动注入了,而没有使用 EnableConfigurationProperties 去声明属性配置类。 像上面说的同样声明就能够正常运行了

参考连接

相关文章
相关标签/搜索