Spring Boot 上传文件教程展示了如何使用 Spring Boot 框架上传单个文件。
Spring 是流行的 Java 应用框架,而 Spring Boot 是 Spring 的演进,可以帮助轻松地创建独立的,生产级的基于 Spring 的应用。
HTML 表单的编码类型
POST 请求有三种编码 HTML 表单类型:
application/x-www-form-urlencodedmultipart/form-datatext/plain
application/x-www-form-urlencoded是默认编码,其中值编码在由&分隔的键值元组中。 =字符用于键和值之间。 非字母数字字符采用百分比编码。 此编码类型不适用于二进制文件。
multipart/form-data用于非 acsii 数据和二进制文件。 input元素的type属性设置为file。
text/plain用于调试。
Spring 上传文件示例
在下面的示例中,我们有一个 Web 表单来选择要上传到服务器的文件。 该文件被上传到/var/www/upload目录。
上传目录
/var/www目录是 Debian Linux 中 Web 内容的标准目录。
$ ls -ld /var/www/upload/drwxrwxr-x 2 www-data www-data 4096 Dec 3 14:29 /var/www/upload/
我们将文件上传到/var/www/upload目录。 www-data组中的用户可以修改目录文件。 因此,运行 Web 服务器的用户必须在此组中。
应用
以下是 Spring Boot Web 应用的来源。
pom.xmlsrc├───main│ ├───java│ │ └───com│ │ └───zetcode│ │ │ Application.java│ │ ├───controller│ │ │ MyController.java│ │ ├───exception│ │ │ StorageException.java│ │ └───service│ │ StorageService.java│ └───resources│ │ application.properties│ └───static│ failure.html│ index.html│ success.html└───test└───java
这是 Spring 应用的项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?><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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.zetcode</groupId><artifactId>springbootuploadfile</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.9.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
这是 Maven pom.xml文件。
com/zetcode/controller/MyController.java
package com.zetcode.controller;import com.zetcode.exception.StorageException;import com.zetcode.service.StorageService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.multipart.MultipartFile;@Controllerpublic class MyController {@Autowiredprivate StorageService storageService;@RequestMapping(value = "/doUpload", method = RequestMethod.POST,consumes = {"multipart/form-data"})public String upload(@RequestParam MultipartFile file) {storageService.uploadFile(file);return "redirect:/success.html";}@ExceptionHandler(StorageException.class)public String handleStorageFileNotFound(StorageException e) {return "redirect:/failure.html";}}
MyController从请求中读取文件并将其保存到所选目录中。
@Autowiredprivate StorageService storageService;
StoreageService将文件存储在磁盘上。
@RequestMapping(value = "/doUpload", method = RequestMethod.POST,consumes = {"multipart/form-data"})public String upload(@RequestParam MultipartFile file) {
upload()方法映射到doUpload URL 模式。 由于我们正在将数据发送到服务器,因此我们使用 POST 请求。 请求参数具有MultipartFile类型。
return "redirect:/success.html";
成功上传文件后,我们会显示一条消息。
@ExceptionHandler(StorageException.class)public String handleStorageFileNotFound(StorageException e) {return "redirect:/failure.html";}
我们有StorageException的处理器。
com/zetcode/StorageException.java
package com.zetcode.exception;public class StorageException extends RuntimeException {public StorageException(String message) {super(message);}public StorageException(String message, Throwable cause) {super(message, cause);}}
这是我们的自定义StorageException。 当文件无法存储在文件系统上时,将引发该错误。
com/zetcode/service/StorageService.java
package com.zetcode.service;import com.zetcode.exception.StorageException;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;import org.springframework.web.multipart.MultipartFile;import java.io.IOException;import java.nio.file.Files;import java.nio.file.Paths;import java.nio.file.StandardCopyOption;@Servicepublic class StorageService {@Value("${upload.path}")private String path;public void uploadFile(MultipartFile file) {if (file.isEmpty()) {throw new StorageException("Failed to store empty file");}try {var fileName = file.getOriginalFilename();var is = file.getInputStream();Files.copy(is, Paths.get(path + fileName),StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {var msg = String.format("Failed to store file", file.getName());throw new StorageException(msg, e);}}}
StorageService从输入流复制数据并将其保存在磁盘上。
@Value("${upload.path}")private String path;
我们使用@Value注解从application.properties文件中读取上传目录。
if (file.isEmpty()) {throw new StorageException("Failed to store empty file");}
我们确保已使用isEmpty()方法选择了一个文件。
var fileName = file.getOriginalFilename();
我们使用getOriginalFilename()方法获得文件名。
var is = file.getInputStream();
我们使用getInputStream()方法获得输入流。
Files.copy(is, Paths.get(path + fileName),StandardCopyOption.REPLACE_EXISTING);
该文件被复制到从与Files.copy()输入流源的目标目录。
resources/application.properties
upload.path=/var/www/upload/
在application.properties中,我们有一个upload.path属性,用于指定上传目录。
resources/static/index.html
<!DOCTYPE html><html><head><title>Uploading file</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body><h1>Uploading file</h1><form action="/doUpload" method="post" enctype="multipart/form-data"><label>Enter file</label><input type="file" name="file"><button type="submit">Upload</button></form></body></html>
这是主页。 它是src/main/resources/static目录中的静态文件。 它包含一个用于选择文件并将其发送到 Spring 应用的表单。
<form action="/doUpload" method="post" enctype="multipart/form-data">
我们选择了doUpload URL 模式。 此表单创建的请求将由 Spring 控制器处理。 enctype属性指定multipart/form-data编码类型,这是使用 HTML 格式上传文件所必需的。
<input type="file" name="file">
input标签的type属性使用户可以选择文件。
<button type="submit">Upload</button>
最后,这是一个提交按钮。
resources/static/success.html
<!DOCTYPE html><html><head><title>Success</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body><p>File successfully uploaded</p></body></html>
文件成功上传到服务器后,将显示success.html。
resources/static/failure.html
<!DOCTYPE html><html><head><title>Failure</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body><p>Failed to upload file</p></body></html>
文件上传失败时,将显示failure.html。
Application.java
package com.zetcode;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}
这段代码设置了 Spring Boot 应用。
在本教程中,我们学习了如何在 Spring 应用中上传文件。 您可能也对相关教程感兴趣: Spring Boot @ExceptionHandler教程, Spring Boot @PathVariable教程, Spring Boot @RequestParam教程, Spring Boot REST H2 教程,独立的 Spring 应用, Java 教程。
