java spring上传_基于Spring实现文件上传功能

本文介绍了如何在Java SpringBoot应用中实现文件上传功能。通过创建一个FileUploadController,使用MultipartFile处理上传请求,借助StorageService接口进行文件存储。文章详细讲解了Controller的各个方法,包括列出已上传文件、下载文件、处理文件上传以及处理文件找不到的情况。同时,还提到了Thymeleaf模板用于前端展示,并展示了如何限制上传文件大小以及应用启动配置。
摘要由CSDN通过智能技术生成

本小节你将建立一个可以接受HTTP multi-part 文件的服务。

你将建立一个后台服务来接收文件以及前台页面来上传文件。

要利用servlet容器上传文件,你要注册一个MultipartConfigElement类,以往需要在web.xml 中配置,

而在这里,你要感谢SpringBoot,一切都为你自动配置好了。

1、新建一个文件上传的Controller:

应用已经包含一些 存储文件 和 从磁盘中加载文件 的类,他们在cn.tiny77.guide05这个包下。我们将会在FileUploadController中用到这些类。

package cn.tiny77.guide05;

import java.io.IOException;

import java.util.List;

import java.util.stream.Collectors;

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;

@Controller

public class FileUploadController {

private final StorageService storageService;

@Autowired

public FileUploadController(StorageService storageService) {

this.storageService = storageService;

}

@GetMapping("/")

public String listUploadedFiles(Model model) throws IOException {

List paths = storageService.loadAll().map(

path -> MvcUriComponentsBuilder.fromMethodName(FileUploadController.class,

"serveFile", path.getFileName().toString()).build().toString())

.collect(Collectors.toList());

model.addAttribute("files", paths);

return "uploadForm";

}

@GetMapping("/files/{filename:.+}")

@ResponseBody

public ResponseEntity 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();

}

}

该类用@Controller注解,因此SpringMvc可以基于它设定相应的路由。每一个@GetMapping和@PostMapping注解将绑定对应的请求参数和请求类型到特定的方法。

GET / 通过StorageService 扫描文件列表并 将他们加载到 Thymeleaf 模板中。它通过MvcUriComponentsBuilder来生成资源文件的连接地址。

GET /files/{filename} 当文件存在时候,将加载文件,并发送文件到浏览器端。通过设置返回头"Content-Disposition"来实现文件的下载。

POST / 接受multi-part文件并将它交给StorageService保存起来。

你需要提供一个服务接口StorageService来帮助Controller操作存储层。接口大致如下

package cn.tiny77.guide05;

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 loadAll();

Path load(String filename);

Resource loadAsResource(String filename);

void deleteAll();

}

以下是接口实现类

package cn.tiny77.guide05;

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.nio.file.StandardCopyOption;

import java.util.stream.Stream;

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;

@Service

public class FileSystemStorageService implements StorageService {

private final Path rootLocation;

@Autowired

public FileSystemStorageService(StorageProperties properties) {

this.rootLocation = Paths.get(properties.getLocation());

}

@Override

public void store(MultipartFile file) {

String filename = StringUtils.cleanPath(file.getOriginalFilename());

try {

if (file.isEmpty()) {

throw new StorageException("无法保存空文件 " + filename);

}

if (filename.contains("..")) {

// This is a security check

throw new StorageException(

"无权访问该位置 "

+ filename);

}

Files.copy(file.getInputStream(), this.rootLocation.resolve(filename),

StandardCopyOption.REPLACE_EXISTING);

}

catch (IOException e) {

throw new StorageException("无法保存文件 " + filename, e);

}

}

@Override

public Stream 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("读取文件异常", 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(

"无法读取文件: " + filename);

}

}

catch (MalformedURLException e) {

throw new StorageFileNotFoundException("无法读取文件: " + filename, e);

}

}

@Override

public void deleteAll() {

FileSystemUtils.deleteRecursively(rootLocation.toFile());

}

@Override

public void init() {

try {

Files.createDirectories(rootLocation);

}

catch (IOException e) {

throw new StorageException("初始化存储空间出错", e);

}

}

}

2、建立一个Html页面

这里使用Thymeleaf模板

File to upload:

页面主要分为三部分分

- 顶部展示SpringMvc传过来的信息

- 一个提供用户上传文件的表单

- 一个后台提供的文件列表

3、限制上传文件的大小

在文件上传的应用中通常要设置文件大小的,想象一下后台处理的文件如果是5GB,那得多糟糕!在SpringBoot中,我们可以通过属性文件来控制。

新建一个application.properties,代码如下:

spring.http.multipart.max-file-size=128KB #文件总大小不能超过128kb

spring.http.multipart.max-request-size=128KB #请求数据的大小不能超过128kb

4、应用启动函数

package cn.tiny77.guide05;

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;

@SpringBootApplication

@EnableConfigurationProperties(StorageProperties.class)

public class Application {

public static void main(String[] args) {

SpringApplication.run(Application.class, args);

}

@Bean

CommandLineRunner init(StorageService storageService) {

return (args) -> {

storageService.deleteAll();

storageService.init();

};

}

}

5、运行结果

ccf00ff9f091eadc54a92ec2ff0cc36a.png

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值