Spring Boot 文件上传与下载的示例代码

文件的上传及下载功能是开发人员在日常应用及编程开发中经常会遇到的。正好最近开发需要用到此功能,虽然本人是 Android 开发人员,但还是业余客串了一下后台开发。

在本文中,您将学习如何使用 Spring Boot 实现 Web 服务中的文件上传和下载功能。首先会构建一个 REST APIs 实现上传及下载的功能,然后使用 Postman 工具来测试这些接口,最后创建一个 Web 界面使用 JavaScript 调用接口演示完整的功能。最终界面及功能如下:

项目环境

- Spring Boot : 2.1.3.RELEASE
- Gredle : 5.2.1
- Java : 1.8
- Intellij IDEA : 2018.3.3

项目创建

开发环境为 Intellij IDEA,项目创建很简单,按照下面的步骤创建即可:

  1. File -> New -> Project...
  2. 选择 Spring Initializr,点击 Next
  3. 填写 Group (项目域名) 和 Artifact (项目别名)
  4. 构建类型可以选择 Maven 或 Gradle, 看个人习惯
  5. 添加 Web 依赖
  6. 输入项目名称及保存路径,完成创建

项目创建完毕之后就可以进行开发,项目的完整结构如下图所示:

参数配置

项目创建完成之后,需要设置一些必要的参数,打开项目resources目录下配置文件application.properties,在其中添加以下参数:

server.port=80

## MULTIPART (MultipartProperties)
# 开启 multipart 上传功能
spring.servlet.multipart.enabled=true
# 文件写入磁盘的阈值
spring.servlet.multipart.file-size-threshold=2KB
# 最大文件大小
spring.servlet.multipart.max-file-size=200MB
# 最大请求大小
spring.servlet.multipart.max-request-size=215MB

## 文件存储所需参数
# 所有通过 REST APIs 上传的文件都将存储在此目录下
file.upload-dir=./uploads

其中file.upload-dir=./uploads参数为自定义的参数,创建FileProperties.javaPOJO类,使配置参数可以自动绑定到POJO类。

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "file")
public class FileProperties {
  private String uploadDir;

  public String getUploadDir() {
    return uploadDir;
  }
  public void setUploadDir(String uploadDir) {
    this.uploadDir = uploadDir;
  }
}

然后在@SpringBootApplication注解的类中添加@EnableConfigurationProperties注解以开启ConfigurationProperties功能。

SpringBootFileApplication.java

@SpringBootApplication
@EnableConfigurationProperties({
    FileProperties.class
})
public class SpringBootFileApplication {

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

配置完成,以后若有file前缀开头的参数需要配置,可直接在application.properties配置文件中配置并更新FileProperties.java即可。

另外再创建一个上传文件成功之后的Response响应实体类UploadFileResponse.java及异常类FileException.java来处理异常信息。

UploadFileResponse.java

public class UploadFileResponse {
  private String fileName;
  private String fileDownloadUri;
  private String fileType;
  private long size;

  public UploadFileResponse(String fileName, String fileDownloadUri, String fileType, long size) {
    this.fileName = fileName;
    this.fileDownloadUri = fileDownloadUri;
    this.fileType = fileType;
    this.size = size;
  }
  // getter and setter ...
}

FileException.java

public class FileException extends RuntimeException{
  public FileException(String message) {
    super(message);
  }

  public FileException(String message, Throwable cause) {
    super(message, cause);
  }
}

创建接口

下面需要创建文件上传下载所需的 REST APIs 接口。创建文件FileController.java

import com.james.sample.file.dto.UploadFileResponse;
import com.james.sample.file.service.FileService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@RestController
public class FileController {

  private static final Logger logger = LoggerFactory.getLogger(FileController.class);

  @Autowired
  private FileService fileService;

  @PostMapping("/uploadFile")
  public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file){
    String fileName = fileService.storeFile(file);

    String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
        .path("/downloadFile/")
        .path(fileName)
        .toUriString();

    return new UploadFileResponse(fileName, fileDownloadUri,
        file.getContentType(), file.getSize());
  }

  @PostMapping("/uploadMultipleFiles")
  public List<UploadFileResponse> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
    return Arrays.stream(files)
        .map(this::uploadFile)
        .collect(Collectors.toList());
  }

  @GetMapping("/downloadFile/{fileName:.+}")
  public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request) {
    // Load file as Resource
    Resource resource = fileService.loadFileAsResource(fileName);

    // Try to determine file's content type
    String contentType = null;
    try {
      contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
    } catch (IOException ex) {
      logger.info("Could not determine file type.");
    }

    // Fallback to the default content type if type could not be determined
    if(contentType == null) {
      contentType = "application/octet-stream";
    }

    return ResponseEntity.ok()
        .contentType(MediaType.parseMediaType(contentType))
        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
        .body(resource);
  }
}

FileController类在接收到用户的请求后,使用FileService类提供的storeFile()方法将文件写入到系统中进行存储,其存储目录就是之前在application.properties配置文件中的file.upload-dir参数的值./uploads

下载接口downloadFile()在接收到用户请求之后,使用FileService类提供的loadFileAsResource()方法获取存储在系统中文件并返回文件供用户下载。

FileService.java

import com.james.sample.file.exception.FileException;
import com.james.sample.file.property.FileProperties;
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.StringUtils;
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.nio.file.StandardCopyOption;

@Service
public class FileService {

  private final Path fileStorageLocation; // 文件在本地存储的地址

  @Autowired
  public FileService(FileProperties fileProperties) {
    this.fileStorageLocation = Paths.get(fileProperties.getUploadDir()).toAbsolutePath().normalize();
    try {
      Files.createDirectories(this.fileStorageLocation);
    } catch (Exception ex) {
      throw new FileException("Could not create the directory where the uploaded files will be stored.", ex);
    }
  }

  /**
   * 存储文件到系统
   *
   * @param file 文件
   * @return 文件名
   */
  public String storeFile(MultipartFile file) {
    // Normalize file name
    String fileName = StringUtils.cleanPath(file.getOriginalFilename());

    try {
      // Check if the file's name contains invalid characters
      if(fileName.contains("..")) {
        throw new FileException("Sorry! Filename contains invalid path sequence " + fileName);
      }

      // Copy file to the target location (Replacing existing file with the same name)
      Path targetLocation = this.fileStorageLocation.resolve(fileName);
      Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

      return fileName;
    } catch (IOException ex) {
      throw new FileException("Could not store file " + fileName + ". Please try again!", ex);
    }
  }

  /**
   * 加载文件
   * @param fileName 文件名
   * @return 文件
   */
  public Resource loadFileAsResource(String fileName) {
    try {
      Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
      Resource resource = new UrlResource(filePath.toUri());
      if(resource.exists()) {
        return resource;
      } else {
        throw new FileException("File not found " + fileName);
      }
    } catch (MalformedURLException ex) {
      throw new FileException("File not found " + fileName, ex);
    }
  }
}

接口测试

在完成上述的代码之后,打开SpringBootFileApplication.java并运行,运行完成之后就可以使用 Postman 进行测试了。

单个文件上传结果:

多个文件上传结果:

文件下载结果:

Web 前端开发

index.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <!-- Required meta tags -->
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>Spring Boot File Upload / Download Rest API Example</title>

  <!-- Bootstrap CSS -->
  <link href="/css/main.css" rel="external nofollow" rel="stylesheet"/>
</head>
<body>

<noscript>
  <h2>Sorry! Your browser doesn't support Javascript</h2>
</noscript>

<div class="upload-container">
  <div class="upload-header">
    <h2>Spring Boot File Upload / Download Rest API Example</h2>
  </div>
  <div class="upload-content">
    <div class="single-upload">
      <h3>Upload Single File</h3>
      <form id="singleUploadForm" name="singleUploadForm">
        <input id="singleFileUploadInput" type="file" name="file" class="file-input" required/>
        <button type="submit" class="primary submit-btn">Submit</button>
      </form>
      <div class="upload-response">
        <div id="singleFileUploadError"></div>
        <div id="singleFileUploadSuccess"></div>
      </div>
    </div>
    <div class="multiple-upload">
      <h3>Upload Multiple Files</h3>
      <form id="multipleUploadForm" name="multipleUploadForm">
        <input id="multipleFileUploadInput" type="file" name="files" class="file-input" multiple required/>
        <button type="submit" class="primary submit-btn">Submit</button>
      </form>
      <div class="upload-response">
        <div id="multipleFileUploadError"></div>
        <div id="multipleFileUploadSuccess"></div>
      </div>
    </div>
  </div>
</div>

<!-- Optional JavaScript -->
<script src="/js/main.js"></script>
</body>
</html>

main.css

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 0;
  font-weight: 400;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.58;
  color: #333;
  background-color: #f4f4f4;
}

body:before {
  height: 50%;
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background: #128ff2;
  content: "";
  z-index: 0;
}

.clearfix:after {
  display: block;
  content: "";
  clear: both;
}

h1, h2, h3, h4, h5, h6 {
  margin-top: 20px;
  margin-bottom: 20px;
}

h1 {
  font-size: 1.7em;
}

a {
  color: #128ff2;
}

button {
  box-shadow: none;
  border: 1px solid transparent;
  font-size: 14px;
  outline: none;
  line-height: 100%;
  white-space: nowrap;
  vertical-align: middle;
  padding: 0.6rem 1rem;
  border-radius: 2px;
  transition: all 0.2s ease-in-out;
  cursor: pointer;
  min-height: 38px;
}

button.primary {
  background-color: #128ff2;
  box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.12);
  color: #fff;
}

input {
  font-size: 1rem;
}

input[type="file"] {
  border: 1px solid #128ff2;
  padding: 6px;
  max-width: 100%;
}

.file-input {
  width: 100%;
}

.submit-btn {
  display: block;
  margin-top: 15px;
  min-width: 100px;
}

@media screen and (min-width: 500px) {
  .file-input {
    width: calc(100% - 115px);
  }

  .submit-btn {
    display: inline-block;
    margin-top: 0;
    margin-left: 10px;
  }
}

.upload-container {
  max-width: 700px;
  margin-left: auto;
  margin-right: auto;
  background-color: #fff;
  box-shadow: 0 1px 11px rgba(0, 0, 0, 0.27);
  margin-top: 60px;
  min-height: 400px;
  position: relative;
  padding: 20px;
}

.upload-header {
  border-bottom: 1px solid #ececec;
}

.upload-header h2 {
  font-weight: 500;
}

.single-upload {
  padding-bottom: 20px;
  margin-bottom: 20px;
  border-bottom: 1px solid #e8e8e8;
}

.upload-response {
  overflow-x: hidden;
  word-break: break-all;
}

main.js

'use strict';

var singleUploadForm = document.querySelector('#singleUploadForm');
var singleFileUploadInput = document.querySelector('#singleFileUploadInput');
var singleFileUploadError = document.querySelector('#singleFileUploadError');
var singleFileUploadSuccess = document.querySelector('#singleFileUploadSuccess');

var multipleUploadForm = document.querySelector('#multipleUploadForm');
var multipleFileUploadInput = document.querySelector('#multipleFileUploadInput');
var multipleFileUploadError = document.querySelector('#multipleFileUploadError');
var multipleFileUploadSuccess = document.querySelector('#multipleFileUploadSuccess');

function uploadSingleFile(file) {
  var formData = new FormData();
  formData.append("file", file);

  var xhr = new XMLHttpRequest();
  xhr.open("POST", "/uploadFile");

  xhr.onload = function() {
    console.log(xhr.responseText);
    var response = JSON.parse(xhr.responseText);
    if(xhr.status == 200) {
      singleFileUploadError.style.display = "none";
      singleFileUploadSuccess.innerHTML = "<p>File Uploaded Successfully.</p><p>DownloadUrl : <a href='" + response.fileDownloadUri + "' target='_blank'>" + response.fileDownloadUri + "</a></p>";
      singleFileUploadSuccess.style.display = "block";
    } else {
      singleFileUploadSuccess.style.display = "none";
      singleFileUploadError.innerHTML = (response && response.message) || "Some Error Occurred";
    }
  }

  xhr.send(formData);
}

function uploadMultipleFiles(files) {
  var formData = new FormData();
  for(var index = 0; index < files.length; index++) {
    formData.append("files", files[index]);
  }

  var xhr = new XMLHttpRequest();
  xhr.open("POST", "/uploadMultipleFiles");

  xhr.onload = function() {
    console.log(xhr.responseText);
    var response = JSON.parse(xhr.responseText);
    if(xhr.status == 200) {
      multipleFileUploadError.style.display = "none";
      var content = "<p>All Files Uploaded Successfully</p>";
      for(var i = 0; i < response.length; i++) {
        content += "<p>DownloadUrl : <a href='" + response[i].fileDownloadUri + "' target='_blank'>" + response[i].fileDownloadUri + "</a></p>";
      }
      multipleFileUploadSuccess.innerHTML = content;
      multipleFileUploadSuccess.style.display = "block";
    } else {
      multipleFileUploadSuccess.style.display = "none";
      multipleFileUploadError.innerHTML = (response && response.message) || "Some Error Occurred";
    }
  }

  xhr.send(formData);
}

singleUploadForm.addEventListener('submit', function(event){
  var files = singleFileUploadInput.files;
  if(files.length === 0) {
    singleFileUploadError.innerHTML = "Please select a file";
    singleFileUploadError.style.display = "block";
  }
  uploadSingleFile(files[0]);
  event.preventDefault();
}, true);

multipleUploadForm.addEventListener('submit', function(event){
  var files = multipleFileUploadInput.files;
  if(files.length === 0) {
    multipleFileUploadError.innerHTML = "Please select at least one file";
    multipleFileUploadError.style.display = "block";
  }
  uploadMultipleFiles(files);
  event.preventDefault();
}, true);

总结

至此,文件的上传及下载功能已完成。在正式环境中可能还需要将上传的文件存储到数据库,此处按照实际需求去处理即可。

本文源代码地址:https://github.com/JemGeek/SpringBoot-Sample/tree/master/SpringBoot-File

本文参考(需要FQ):https://www.callicoder.com/spring-boot-file-upload-download-rest-api-example/

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

(0)

相关推荐

  • springboot实现文件上传和下载功能

    spring boot 引入"约定大于配置"的概念,实现自动配置,节约了开发人员的开发成本,并且凭借其微服务架构的方式和较少的配置,一出来就占据大片开发人员的芳心.大部分的配置从开发人员可见变成了相对透明了,要想进一步熟悉还需要关注源码. 1.文件上传(前端页面): <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/lo

  • SpringBoot实现文件上传下载功能小结

    最近做的一个项目涉及到文件上传与下载.前端上传采用百度webUploader插件.有关该插件的使用方法还在研究中,日后整理再记录.本文主要介绍SpringBoot后台对文件上传与下载的处理. 单文件上传 // 单文件上传 @RequestMapping(value = "/upload") @ResponseBody public String upload(@RequestParam("file") MultipartFile file) { try { if (

  • 详解SpringBoot文件上传下载和多文件上传(图文)

    最近在学习SpringBoot,以下是最近学习整理的实现文件上传下载的Java代码: 1.开发环境: IDEA15+ Maven+JDK1.8 2.新建一个maven工程: 3.工程框架 4.pom.xml文件依赖项 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation

  • Spring Boot + thymeleaf 实现文件上传下载功能

    最近同事问我有没有有关于技术的电子书,我打开电脑上的小书库,但是邮件发给他太大了,公司又禁止用文件夹共享,于是花半天时间写了个小的文件上传程序,部署在自己的Linux机器上. 提供功能: 1 .文件上传 2.文件列表展示以及下载 原有的上传那块很丑,写了点js代码优化了下,最后界面显示如下图: 先给出成果,下面就一步步演示怎么实现. 1.新建项目 首先当然是新建一个spring-boot工程,你可以选择在网站初始化一个项目或者使用IDE的Spring Initialier功能,都可以新建一个项目

  • springboot 中文件上传下载实例代码

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. Spring Boot特点 1. 创建独立的Spring应用程序 2. 嵌入的Tomcat,无需部署WAR文件 3. 简化Maven配置 4. 自动配置Spr

  • SpringBoot 文件上传和下载的实现源码

    本篇文章介绍SpringBoot的上传和下载功能. 一.创建SpringBoot工程,添加依赖 compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-starter-thymeleaf") 工程目录为: Application.java 启动类 package hello; import org.springf

  • SpringBoot后台实现文件上传下载

    SpringBoot后台如何实现文件上传下载? 最近做的一个项目涉及到文件上传与下载.前端上传采用百度webUploader插件.有关该插件的使用方法还在研究中,日后整理再记录.本文主要介绍SpringBoot后台对文件上传与下载的处理. 单文件上传 // 单文件上传 @RequestMapping(value = "/upload") @ResponseBody public String upload(@RequestParam("file") Multipar

  • Spring Boot 文件上传与下载的示例代码

    文件的上传及下载功能是开发人员在日常应用及编程开发中经常会遇到的.正好最近开发需要用到此功能,虽然本人是 Android 开发人员,但还是业余客串了一下后台开发. 在本文中,您将学习如何使用 Spring Boot 实现 Web 服务中的文件上传和下载功能.首先会构建一个 REST APIs 实现上传及下载的功能,然后使用 Postman 工具来测试这些接口,最后创建一个 Web 界面使用 JavaScript 调用接口演示完整的功能.最终界面及功能如下: 项目环境 - Spring Boot

  • PHP实现文件上传和下载的示例代码

    目录 1.效果图 2.首先是封装好的图片类(缩放及生成水印) 1.GDBasic.php 2.Image.php 3.ajax类封装文件 1.index.php 2.图片相关功能处理 3.封装好的文件上传类 4.搜索功能实现 4.最后数据库格式 1.效果图 2.首先是封装好的图片类(缩放及生成水印) 1.GDBasic.php <?php /** * GDBasic.php * description GD基础类 */ namespace test\Lib; class GDBasic { pr

  • Spring Boot 文件上传原理解析

    首先我们要知道什么是Spring Boot,这里简单说一下,Spring Boot可以看作是一个框架中的框架--->集成了各种框架,像security.jpa.data.cloud等等,它无须关心配置可以快速启动开发,有兴趣可以了解下自动化配置实现原理,本质上是 spring 4.0的条件化配置实现,深抛下注解,就会看到了. 说Spring Boot 文件上传原理 其实就是Spring MVC,因为这部分工作是Spring MVC做的而不是Spring Boot,那么,SpringMVC又是怎么

  • Spring Boot文件上传最新解决方案

    一.创建一个简单的包含WEB依赖的SpringBoot项目 pom.xml内容: <!-- Spring Boot web启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- jsp --> <d

  • SpringMVC文件上传及查看的示例代码

    写在前面 谈到文件上传,首先要说业务逻辑,如果上传的文件大家都可以看(比如广告或者首页的banner)等,那么我们就把图片放在静态资源区(与css,js一样的位置)中,如果文件是受保护的(像用户只能查看自己上传的照片),那么我们就把它存放在服务器中的某个专门存放图片的位置. 本例分别展示了存放在两个位置的上传文件的方法,上传之后,作为延伸,还添加了查看上传的文件以及下载已经上传的文件的功能. 准备工作 配置SpringMVC,导入commons包 在mvc-servlet.xml中配置文件上传解

  • Spring Boot文件上传简单实例代码

    上传文件是我们日常使用最为广泛的功能之一,比如App端上传头像.本章演示如何从客户端上传到 Spring Boot 开发的 Api中. https://github.com/fishpro/spring-boot-study/tree/master/spring-boot-study-upload 1 新建 Spring Boot Maven 示例工程项目 注意:本示例是用 IDEA 开发工具 File > New > Project,如下图选择 Spring Initializr 然后点击

  • SpringBoot实现文件上传与下载功能的示例代码

    目录 Spring Boot文件上传与下载 举例说明 1.引入Apache Commons FileUpload组件依赖 2.设置上传文件大小限制 3.创建选择文件视图页面 4.创建控制器 5.创建文件下载视图页面 6.运行 Spring Boot文件上传与下载 在实际的Web应用开发中,为了成功上传文件,必须将表单的method设置为post,并将enctype设置为multipart/form-data.只有这种设置,浏览器才能将所选文件的二进制数据发送给服务器. 从Servlet 3.0开

  • Axios+Spring Boot实现文件上传和下载

    本文实例为大家分享了Axios+Spring Boot实现文件上传和下载的具体代码,供大家参考,具体内容如下 1.所用技术 前端:Vue + Axios 后端:Springboot + SpringMVC 2.单文件上传 后端代码 只需要使用MultipartFile类配合RequestBody注解即可 @PostMapping("your/path") public ResultData courseCoverUpload(@RequestBody MultipartFile fil

  • Spring MVC实现文件上传和下载

    本文实例为大家分享了Spring MVC实现文件上传和下载的具体代码,供大家参考,具体内容如下 文件上传 1.导入主要依赖 <!--文件上传--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependen

  • springMVC实现文件上传和下载

    本文实例为大家分享了springMVC实现文件上传和下载的具体代码,供大家参考,具体内容如下 1准备工作 web.xml文件导入DispatcherServlet,CharacterEncodingFilter <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet

随机推荐