SpringBoot实现文件的上传与下载

  • 构建有个SpringBoot工程,在pom.xml文件中添加依赖
<dependency>
   		<groupId>org.springframework.boot</groupId>
   		<artifactId>spring-boot-starter-thymeleaf</artifactId>
   	</dependency>
   	<dependency>
   		<groupId>org.springframework.boot</groupId>
   		<artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • 创建一个上传和下载文件的controller
package com.liuyong.controller;

import com.liuyong.exception.StorageFileNotFoundException;
import com.liuyong.service.StorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
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 org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.io.IOException;
import java.util.stream.Collectors;

@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().toUri().toString())
               .collect(Collectors.toList()));

       return "uploadForm";
   }

   @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:/";
   }
}

1.@GetMapping("/"):从StorageService中查找上传文件的当前列表,并将其加载到一个Thymeleaf模板中
2.@GetMapping("/files/{filename:.+}"):加载资源,并将其发送到浏览器下载
3.@PostMapping("/"):保存文件

  • 创建一个处理文件上传和下载的service接口
package com.liuyong.service;

import org.springframework.core.io.Resource;
import org.springframework.web.multipart.MultipartFile;

import java.nio.file.Path;
import java.util.stream.Stream;

public interface StorageService {
   void init();

   void store(MultipartFile file);

   Stream<Path> loadAll();

   Path load(String filename);

   Resource loadAsResource(String filename);

   void deleteAll();
}
  • 创建一个处理文件上传和下载的service实现类
package com.liuyong.service;

import com.liuyong.configuration.StorageProperties;
import com.liuyong.exception.StorageException;
import com.liuyong.exception.StorageFileNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

@Service
public class StorageServiceImpl implements StorageService {

   private final Path rootLocation;

   @Autowired
   public StorageServiceImpl(StorageProperties properties) {
       this.rootLocation = Paths.get(properties.getLocation());
   }

   @Override
   public void store(MultipartFile file) {
       try {
           if (file.isEmpty()) {
               throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
           }
           Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename()));
       } catch (IOException e) {
           throw new StorageException("Failed to store file " + file.getOriginalFilename(), e);
       }
   }

   @Override
   public Stream<Path> loadAll() {
       try {
           return Files.walk(this.rootLocation, 1)
                   .filter(path -> !path.equals(this.rootLocation))
                   .map(path -> this.rootLocation.relativize(path));
       } catch (IOException e) {
           throw new StorageException("Failed to read stored files", e);
       }

   }

   @Override
   public Path load(String filename) {
       return rootLocation.resolve(filename);
   }

   @Override
   public Resource loadAsResource(String filename) {
       try {
           Path file = load(filename);
           Resource resource = new UrlResource(file.toUri());
           if(resource.exists() || resource.isReadable()) {
               return resource;
           }
           else {
               throw new StorageFileNotFoundException("Could not read file: " + filename);

           }
       } catch (MalformedURLException e) {
           throw new StorageFileNotFoundException("Could not read file: " + filename, e);
       }
   }

   @Override
   public void deleteAll() {
       FileSystemUtils.deleteRecursively(rootLocation.toFile());
   }

   @Override
   public void init() {
       try {
           Files.createDirectory(rootLocation);
       } catch (IOException e) {
           throw new StorageException("Could not initialize storage", e);
       }
   }
}

  • 创建HTML文件,提供上传和下载文件的页面
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<body>
<div th:if="${message}">
   <h2 th:text="${message}"/>
</div>

<div>
   <form method="POST" enctype="multipart/form-data" action="/">
       <table>
           <tr>
               <td>File to upload:</td>
               <td><input type="file" name="file"/></td>
           </tr>
           <tr>
               <td></td>
               <td><input type="submit" value="Upload"/></td>
           </tr>
       </table>
   </form>
</div>

<div>
   <ul>
       <li th:each="file : ${files}">
           <a th:href="${file}" th:text="${file}"/>
       </li>
   </ul>
</div>

</body>
</html>
  • 启动类添加CommandLineRunner
package com.example.uploadingfiles;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import com.example.uploadingfiles.storage.StorageProperties;
import com.example.uploadingfiles.storage.StorageService;

@SpringBootApplication
@EnableConfigurationProperties(StorageProperties.class)
public class UploadingFilesApplication {

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

   @Bean
   CommandLineRunner init(StorageService storageService) {
   	return (args) -> {
   		storageService.deleteAll();
   		storageService.init();
   	};
   }
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值