文件上传与下载在Web应用中是一个比较常见的功能。在本教程中,我将基于Spring 2.2.6版本实现一个基于Restful风格的文件上传与下载APIs。

基于Spring Boot 2.0实战系列源码已经Push到Github仓库:https://github.com/ramostear/... 。感兴趣朋友欢迎Star/Fork。

1. 环境

JDK: Java 1.8

Framework: Spring Boot 2.2.6(Only Using Spring Web MVC)

Maven: Maven 3.5.0+

IDE: IntelliJ IDEA 2019.2

Test: Postman 7.23.0

2. 功能

本教程中,使用Spring 2.2.6实现Restful风格的APIs并提供以下的功能:

1.客户端上传文件到服务端

2.对客户端上传文件大小进行限制(50MB)

3.点击链接地址下载文件

4.获得已上传文件列表(文件名和下载地址)

下面是教程所实现的APIs列表(服务端请求端口默认8080):

请求方式

URL地址

说明

POST

/upload

上传一份文件

GET

/files

获取已上传文件列表

GET

/files/{filename}

根据链接地址下载文件

3.工程结构

工程目录结构说明如下:

1.config/FileUploadConfiguration.java: 常规组件,主要在重启应用时清理历史文件;

2.controller/FileUploadController.java: 主要的控制器,负责处理文件的上传,下载,浏览等请求;

3.exception/FileUploadExceptionAdvice.java: 全局的异常处理类,提供用户友好的异常提示信息;

4.service/FileStorageService.java: 文件上传接口类,提供存储地址初始化,保存文件,加载文件,清理文件等操作;

5.service/impl/FileStorageServiceImpl.java: 文件上传接口实现类;

6.valueobject/UploadFile.java: 封装了文件名和存储地址的POJO类;

7.valueobject/Message.java: 请求/响应的消息对象;

8.resources/application.yml: 项目配置文件,主要配置了文件上传大小限制;

9.pom.xml:Maven依赖配置文件。

4 创建Spring Boot项目

本教程是基于IntelliJ IDEA创建Spring Boot项目的,你也可以选择自己喜欢的IDE创建项目。创建完项目后,请检查pom.xml文件中是否包含如下配置:

org.springframework.boot

spring-boot-starter-web

本教程只使用到Spring Web MVC的功能,因此只需添加spring-boot-starter-web依赖。

4.1 文件上传接口

按照面向接口编程的约定(规范),创建一个用于操作上传文件的接口类FileStorageService.java,并提供相应的方法。

service/FileStorageService.java

package com.ramostear.springboot.uploadfile.service;

import org.springframework.core.io.Resource;

import org.springframework.web.multipart.MultipartFile;

import java.nio.file.Path;

import java.util.stream.Stream;

/**

* @ClassName FileStorageService

* @Description TODO

* @Author 树下魅狐

* @Date 2020/4/28 0028 18:35

* @Version since 1.0

**/

public interface FileStorageService {

void init();

void save(MultipartFile multipartFile);

Resource load(String filename);

Stream load();

void clear();

}

在启动应用时,先调用clear()方法清理历史文件,再调用init()方法初始化文件上传地址。

4.2 实现文件上传接口

文件上传接口实现类比较简单,这里直接给出代码:

service/impl/FileStorageServiceImpl.java

/**

* @ClassName FileStorageServiceImpl

* @Description TODO

* @Author 树下魅狐

* @Date 2020/4/28 0028 18:38

* @Version since 1.0

**/

@Service("fileStorageService")

public class FileStorageServiceImpl implements FileStorageService {

private final Path path = Paths.get("fileStorage");

@Override

public void init() {

try {

Files.createDirectory(path);

} catch (IOException e) {

throw new RuntimeException("Could not initialize folder for upload!");

}

}

@Override

public void save(MultipartFile multipartFile) {

try {

Files.copy(multipartFile.getInputStream(),this.path.resolve(multipartFile.getOriginalFilename()));

} catch (IOException e) {

throw new RuntimeException("Could not store the file. Error:"+e.getMessage());

}

}

@Override

public Resource load(String filename) {

Path file = path.resolve(filename);

try {

Resource resource = new UrlResource(file.toUri());

if(resource.exists() || resource.isReadable()){

return resource;

}else{

throw new RuntimeException("Could not read the file.");

}

} catch (MalformedURLException e) {

throw new RuntimeException("Error:"+e.getMessage());

}

}

@Override

public Stream load() {

try {

return Files.walk(this.path,1)

.filter(path -> !path.equals(this.path))

.map(this.path::relativize);

} catch (IOException e) {

throw new RuntimeException("Could not load the files.");

}

}

@Override

public void clear() {

FileSystemUtils.deleteRecursively(path.toFile());

}

}

其中,Files、Path和Paths是java.nio.file提供的类,Resource是org.springframework.core.io包中提供的类。

4.3 定义值对象

本教程中,定义了两个简单的对象UploadFile.java和Message.java,分别封装了上传文件信息和响应消息,代码如下:

valueobject/UploadFile.java

/**

* @ClassName UploadFile

* @Description TODO

* @Author 树下魅狐

* @Date 2020/4/28 0028 18:48

* @Version since 1.0

**/

public class UploadFile {

private String fileName;

private String url;

public UploadFile(String fileName, String url) {

this.fileName = fileName;

this.url = url;

}

public String getFileName() {

return fileName;

}

public void setFileName(String fileName) {

this.fileName = fileName;

}

public String getUrl() {

return url;

}

public void setUrl(String url) {

this.url = url;

}

}

valueobject/Message.java

/**

* @ClassName Message

* @Description TODO

* @Author 树下魅狐

* @Date 2020/4/28 0028 19:21

* @Version since 1.0

**/

public class Message {

private String message;

public Message(String message) {

this.message = message;

}

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

}

4.4 控制器

在controller包下创建文件上传控制器,用于处理客户端的请求。代码如下:

controller/FileUploadController.java

/**

* @ClassName FileUploadController

* @Description TODO

* @Author 树下魅狐

* @Date 2020/4/28 0028 18:52

* @Version since 1.0

**/

@RestController

public class FileUploadController {

@Autowired

FileStorageService fileStorageService;

@PostMapping("/upload")

public ResponseEntity upload(@RequestParam("file")MultipartFile file){

try {

fileStorageService.save(file);

return ResponseEntity.ok(new Message("Upload file successfully: "+file.getOriginalFilename()));

}catch (Exception e){

return ResponseEntity.badRequest()

.body(new Message("Could not upload the file:"+file.getOriginalFilename()));

}

}

@GetMapping("/files")

public ResponseEntity> files(){

List files = fileStorageService.load()

.map(path -> {

String fileName = path.getFileName().toString();

String url = MvcUriComponentsBuilder

.fromMethodName(FileUploadController.class,

"getFile",

path.getFileName().toString()

).build().toString();

return new UploadFile(fileName,url);

}).collect(Collectors.toList());

return ResponseEntity.ok(files);

}

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

public ResponseEntity getFile(@PathVariable("filename")String filename){

Resource file = fileStorageService.load(filename);

return ResponseEntity.ok()

.header(HttpHeaders.CONTENT_DISPOSITION,

"attachment;filename=\""+file.getFilename()+"\"")

.body(file);

}

}

> 在控制器中,使用@RestController组合注解替换了@Controller+@ResponseBody的注解方式,并采用@RequestMapping的快捷方式注解方法。

4.5配置上传文件大小

通常,出于安全和性能考虑,我们需要限定客户端上传文件的大小,本教程限定的文件大小最大为50MB。在application.yml(application.properties)文件中添加如下配置:

application.yml

spring:

servlet:

multipart:

max-request-size: 50MB

max-file-size: 50MB

application.properties

spring.servlet.multipart.max-request-size=50MB

spring.servlet.multipart.max-file-size=50MB

spring.servlet.multipart.max-request-size=50MB: 单次请求所能上传文件的总文件大小

spring.servlet.multipart.max-file-size=50MB:单个文件所能上传的文件大小

4.6 全局异常处理

在控制器中,文件上传过程中可能产生的异常我们使用try-catch语句进行了用户友好处理,但当客户端上传文件大小超过50MB时,应用会抛出MaxUploadSizeExceededException异常信息,我们需要对此异常信息做处理。最简单的方式是使用@ControllerAdvice+@ExceptionHandler组合方式处理异常。在exception包下创建异常处理类,代码如下:

exception/FileUploadExceptionAdvice.java

/**

* @ClassName FileUploadExceptionAdvice

* @Description TODO

* @Author 树下魅狐

* @Date 2020/4/28 0028 19:10

* @Version since 1.0

**/

@ControllerAdvice

public class FileUploadExceptionAdvice extends ResponseEntityExceptionHandler {

@ExceptionHandler(MaxUploadSizeExceededException.class)

public ResponseEntity handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e){

return ResponseEntity.badRequest().body(new Message("Upload file too large."));

}

}

4.7 初始化文件存储空间

为了在测试时获得干净的测试数据,同时也为了在应用启动后分配好上传文件存储地址,我们需要在config包下创建一个配置类,在应用启动时调用FileStorageService中的clear()方法和init()方法。实现该功能,最快的方式是配置类实现CommandLineRunner接口类的run()方法,代码如下:

config/FileUploadConfiguration.java

@Service

public class FileUploadConfiguration implements CommandLineRunner {

@Autowired

FileStorageService fileStorageService;

@Override

public void run(String... args) throws Exception {

fileStorageService.clear();

fileStorageService.init();

}

}

使用@Autowired注解将FileStorageService注入到FileUploadConfiguration.java中。

5.运行程序并测试

运行Spring Boot应用程序的方式有很多,例如:

1.命令方式:mvn spring-boot:run

2.IntelliJ IDEA:点击IntelliJ IDEA的“Run”按钮

3.main()方法:直接运行主类中的main()方法

4.运行jar包:java -jar springboot-fileupload.jar

选择一种你比较熟悉的方式运行Spring Boot应用程序。当应用程序启动成功后,在项目的根目录会创建一个名为fileStorage的文件夹,该文件夹将用于存放客户端上传的文件。

5.1 使用Postman对APIs进行测试

应用程序启动成功后,我们使用Postman对应用程序中的APIs进行测试。

$调用/upload接口上传文件:

$上传一个大小超过50MB的文件

执行结果:

$检查文件存储文件夹

文件上传成功后,我们可以查看项目根目录下的fileStorage文件夹,检查是否有文件被存储到当中:

$调用/files接口,获取所有已上传文件列表

/files接口将返回所有已上传的文件信息,我们可以点击其中任意一个链接地址下载文件。在Postman中,可以通过header选项卡查看响应头中文件的详细信息,例如:

你也可以复制列表中的链接地址,并在浏览器中访问该地址,浏览器会弹出一个下载询问对话框,点击确定按钮进行下载。

6 总结

本章节介绍了Spring Boot 2.0实现基于Restful风格的文件上传和下载APIs,并使用Postman工具对APIs进行测试,达到了设计的预期结果。你可以通过下面的链接地址获取本次教程的相关源代码。

如果你在运行本次教程提供的源代码过程中遇到什么问题,请在评论区与我联系。

未经允许,请勿转载!

java restful文件传输_Spring Boot 2.0实现基于Restful风格的文件上传与下载APIs相关推荐

  1. WSE3.0构建Web服务安全(4):MTOM消息传输优化和文件上传、下载

    MTOM消息优化传输机制主要应用于大量数据的传输,很多文章中也直接得出结论:使用MTOM文件传输效率高.为什么MTOM的数据传输效率会比别的方式要高?MTOM真的如此完美吗,它有什么不足?什么情况下使 ...

  2. springboot传入json和文件_Spring Boot之 Controller 接收参数和返回数据总结(包括上传、下载文件)...

    server: port: 8088 servlet: context-path: /sid spring: mvc: view: prefix: / suffix: .html /** * 返回界面 ...

  3. java spring文件下载_SpringMVC实现文件上传和下载的工具类

    本文主要目的是记录自己基于SpringMVC实现的文件上传和下载的工具类的编写,代码经过测试可以直接运行在以后的项目中. 开发的主要思路是对上传和下载文件进行抽象,把上传和下载的核心功能抽取出来分装成 ...

  4. 从服务器上传和下载文件方法

    1. ssh 安装SSH Secure Shell Client客户端 下载链接 http://download.csdn.net/detail/jiandanjinxin/9755684 使用方法参 ...

  5. Java连接FTP服务器并且实现对其文件的上传和下载

    概述 FTP是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为"文传协议".FTP作为网络共享文件的传输协议,在网络应用软件中具有广泛的应用.F ...

  6. java 中 FtpClient 实现 FTP 文件上传、下载

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 源代码大部分是网上找的,查来查去,找到几个可以用的例子,改来改去,揉合成现在这个样子. 一. jar ...

  7. java实现ftp连接、登陆、上传、下载、删除文件、获取目录、文件列表

    全栈工程师开发手册 (作者:栾鹏) java教程全解 java实现ftp连接.登陆.上传.下载.删除文件.获取目录.文件列表等操作. 本地调试,首先需要在本机上开启ftp服务和ftp站点. 测试代码 ...

  8. java文件实现文件的上传和下载

    ·        简介 文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文 ...

  9. 超详细的文件上传和下载(Spring Boot)

    超详细的文件上传和下载 前言Ⅰ:@RequestParam和@RequestPart的区别 @RequestPart @RequestPart这个注解用在multipart/form-data表单提交 ...

  10. 全栈开发实战|Spring Boot文件上传与下载

    文件上传与下载是Web应用开发中常用的功能之一.接下来我们将讨论如何在Spring Boot的Web应用开发中,如何实现文件的上传与下载. 01.Spring Boot文件上传与下载 在实际的Web应 ...

最新文章

  1. PCL中多个可视化窗口
  2. 工作发狂:Mybatis 中$和#千万不要乱用!
  3. JVM源码分析之安全点safepoint
  4. MVC3+Entity Framework 实现投票系统(一)
  5. How is setModel triggering propery binding
  6. 1618D. Array and Operations
  7. 模型稳定后放在服务器上,把工程放在服务器上
  8. linux 上plsql命令_在 Linux 上压缩文件:zip 命令的各种变体及用法 | Linux 中国
  9. Centos5.11 使用yum源
  10. javaSE---一个小项目(ATM机)
  11. stupid soso spider
  12. 开课吧课堂:人工智能对金融行业的影响
  13. 微信接入之获取用户头像
  14. 安卓终端模拟器运行PHP,ROOT用户福利:安卓终端模拟器简述及命令行入门!
  15. 解决YOLOv5算法中的中文标签显示问题
  16. HTML5~问卷调查页面的设计与实现
  17. 360手机官方刷机教程(N6系列+N7系列通用)
  18. int *p=malloc(100); 求 sizeof(p)
  19. Linux基础Day02
  20. Java内存分析工具MAT(Memory Analyzer Tool)的介绍与使用

热门文章

  1. 实验六:流类库与I/O
  2. sql server 2016新特性 查询存储(Query Store)的性能影响
  3. 【bzoj 2461】[BeiJing2011]符环(高维dp+记忆化搜索)
  4. WCF中NetTCp配置
  5. 30岁之前创业想成功必看
  6. 程序员应该学会自我学习
  7. Keras 学习笔记
  8. 三枪手决斗问题的计算机解答
  9. 20191208_神经网络搭建_缺失值箱型图
  10. ACM金牌选手算法讲解《线性表》