SpringBoot官网例子(5)——Uploading Files(上传文件)

1、准备工作

原文:https://spring.io/guides/gs/uploading-files/

  • >=1.8的JDK
  • Eclipse(其它任何合适的IDE)
  • Maven3.2(官网也有Gradle的构建

2、 POM文件

仍然是一个子模块,父工程的pom https://blog.youkuaiyun.com/csdn86868686888/article/details/103758256

<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>com.springboot</groupId>
    <artifactId>springboot-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>springboot-UploadingFiles</artifactId>
  
    <properties>
        <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-thymeleaf</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>

其中的thymeleaf是一个模板的渲染引擎。

 

3、工程

工程结构:

代码:

单独开一个接口出来,这与跟数据库交互时出一个接口一样,主要是为了适配不同的存储系统,到时候面向接口编程,实现根据自己的系统具体适配就行。

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

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

public interface StorageService {
	void init();
	void store(MultipartFile file);
	Stream<Path> loadAll();
	Path load(String filename);
	Resource loadAsResource(String filename);
	void deleteAll();
}

其中的一个实现:

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.springboot.Application;

@Service
public class FileSystemStorageService implements StorageService{
	
	private final Path rootLocation;
	
	private static final Logger log = LoggerFactory.getLogger(FileSystemStorageService.class);
	
	@Autowired
	public FileSystemStorageService(StorageProperties properties) {
		this.rootLocation = Paths.get(properties.getLocation());
	}
	
	@Override
	public void init() {//创建文件夹
		try {
			Files.createDirectories(rootLocation);//连续创建一系列文件夹
		}
		catch (IOException e) {
			throw new StorageException("Could not initialize storage", e);
		}
	}

	@Override
	public void store(MultipartFile file) {//存储文件
		String filename = StringUtils.cleanPath(file.getOriginalFilename());//文件名
		log.info(filename);
		try {
			if (file.isEmpty()) {
				throw new StorageException("Failed to store empty file " + filename);
			}
			if (filename.contains("..")) {
				throw new StorageException(
						"Cannot store file with relative path outside current directory "
								+ filename);
			}
			try (InputStream inputStream = file.getInputStream()) {
				Files.copy(inputStream, this.rootLocation.resolve(filename),
					StandardCopyOption.REPLACE_EXISTING);
				log.info(this.rootLocation.resolve(filename).toString());
			}
		}
		catch (IOException e) {
			throw new StorageException("Failed to store file " + filename, e);
		}
	}

	@Override
	public Stream<Path> loadAll() {//获取所有的文件名
		try {
			return Files.walk(this.rootLocation, 1)
				.filter(path -> !path.equals(this.rootLocation))
				.map(this.rootLocation::relativize);
		}
		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());
			log.info(resource.toString());
			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());
	}

}

控制器

package com.springboot.controller;

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

import org.slf4j.Logger;
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.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.springboot.service.StorageFileNotFoundException;
import com.springboot.service.StorageService;

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

	  @ExceptionHandler(StorageFileNotFoundException.class)
	  public ResponseEntity<?> handleStorageFileNotFound(StorageFileNotFoundException exc) {
	    return ResponseEntity.notFound().build();
	  }
	
}

页面 :

<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>

 其余部分代码见文末链接。

4、总结

实现的效果是这样的:

 这里边涉及到的一些知识是,Thymeleaf模板的使用,Spring一些常用的工具类比如FileSysytemUtil,Stringutil等,还有一些Files,Path类对路径、文件等的处理,java8中Lambda表达式,函数式接口等等。

代码戳https://github.co/github20131983/springboot

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值