本文以 SpringBoot 实现一个 文件上传的简单操作,可实现控制文件上传大小,文件上传路径。
创建一个SpringBoot项目,创建SpringBoot 项目同时添加 webapp 文件夹 用于放 html 页面。
项目结构:
可能你创建的SpringBoot项目没有webapp文件夹,我也为你准备了解决办法。
解决方法:
点击工具栏 Project Structure 按钮[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q3L0GiXU-1598349113955)(C:\Users\hainei-developer\Desktop\微信截图_20200825164438.png)],在打开的窗口中选中 Moudles -> Web,按照步骤添加配置:
项目有webapps文件夹了吧,继续来看文件上传吧!↓
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
完整pom.xml,在build中添加resource保证在webapps下面的html文件进行编译。
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.3.RELEASEversion>
<relativePath/>
parent>
<groupId>com.ifknowgroupId>
<artifactId>spring-boot-fileuploadartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>spring-boot-fileuploadname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
<exclusions>
<exclusion>
<groupId>org.junit.vintagegroupId>
<artifactId>junit-vintage-engineartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.12version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
<resources>
<resource>
<directory>src/main/webappdirectory>
<targetPath>META-INF/resourcestargetPath>
<includes>
<include>**/**include>
includes>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<filtering>truefiltering>
<includes>
<include>**/*include>
includes>
resource>
resources>
build>
project>
配置项目上传路径和文件上传大小。
server:
port: 8081
# 文件上传路径配置
my:
uploadFile:
uploadPath: C:\softInstall\Tomcat 8.5\webapps\fileupload\
readPath: \fileupload\
# 文件上传大小
spring:
servlet:
multipart:
enabled: true
file-size-threshold: 0
max-file-size: 200MB
max-request-size: 200MB
编写一个HTML页面,页面上一个file的button,
为了展现技术,很无聊的加了一个简陋的进度条。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传title>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js">script>
head>
<style>
.box {
height: 30px;
width: 200px;
border: 1px solid green;
margin-top: 30px;
}
article {
height: 100%;
width: 0;
background: palegreen;
}
style>
<body>
<input type="file" id="file">
<div class="box">
<article class="cont">article>
div>
<a id="back" href="#">##a>
body>
<script>
function uploadImg(fileInfo) {
const data = new FormData();
data.append('file', fileInfo)
return new Promise((reslove, reject) => {
$.ajax({
type: 'post',
url: '/file/upload',
data,
processData: false,
contentType: false,
xhr() {
const myXhr = $.ajaxSettings.xhr();
myXhr.upload.addEventListener('progress', (e) => {
console.log(e.loaded, e.total)
document.querySelector('.cont').style.width = `${(e.loaded / e.total) * 100}%`
})
return myXhr
},
success(data) {
console.log(data.url)
$("#back").attr("href", "http://localhost:8080" + data.url)
$("#back").text(data.newName)
},
error() {
}
})
})
}
const file = document.querySelector('#file');
file.onchange = function (e) {
document.querySelector('.cont').style.width = '0px'
const files = e.target.files;
[...files].forEach((res) => {
uploadImg(res).then((res) => {
}, (err) => {
})
})
}
script>
html>
package com.ifknow.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @Author: ifknow
* @Date: 2020/8/25 10:18
* @Description: 读取配置文件中定义的文件上传路径
*/
@Configuration
@ConfigurationProperties(prefix = "my", ignoreUnknownFields = false)
public class ObtainProperties {
/**
* 文件上传配置
*/
private final UploadFile uploadFile = new UploadFile();
public UploadFile getUploadFile() {
return uploadFile;
}
@Data
public static class UploadFile {
private String uploadPath;
private String readPath;
}
}
package com.ifknow.utils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @Author: ifknow
* @Date: 2020/8/25 10:28
* @Description: NO Description
*/
public class FileUtil {
/**
* 上传文件接口
*
* @param file 文件
* @param request
* @param model
* @return
*/
public Map<String, Object> upload(MultipartFile file, HttpServletRequest request, FileModel model) {
//文件不为空
if (!file.isEmpty()) {
//上传文件名
String fileName = file.getOriginalFilename();
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
try {
Map<String, Object> map = this.toUpload(file, suffix, fileName, request, model);
return map;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 上传操作
*
* @param file 文件
* @param suffix 后缀
* @param fileName 文件名
* @param request
* @param model
* @return
*/
public Map<String, Object> toUpload(MultipartFile file, String suffix, String fileName, HttpServletRequest request,FileModel model) {
suffix = suffix.toLowerCase();
Map<String, Object> pathMap = this.filePath(suffix, model);
String filePath = pathMap.get("filePath").toString();
File realPath = new File(filePath, fileName);
if (!realPath.getParentFile().exists()) {
realPath.getParentFile().mkdirs();
}
String newName = UUID.randomUUID().toString().replace("-", "") + fileName.substring(fileName.lastIndexOf("."));
File newFile = new File(filePath + File.separator + newName);
try {
file.transferTo(newFile);
} catch (Exception e) {
e.printStackTrace();
}
String fileType = pathMap.get("fileType").toString();
Map<String, Object> map = new HashMap<String, Object>();
//后缀
map.put("suffix", suffix);
//原文件名
map.put("oldName", fileName.substring(0, fileName.lastIndexOf(".")));
//新文件名
map.put("newName", newName.substring(0, newName.lastIndexOf(".")));
//文件大小
map.put("fileSize", file.getSize());
//路径
map.put("url", model.getReadPath() + fileType + File.separator + newName);
// 类型(0视/1文/2图片)
map.put("type", getTypeByUrl(suffix));
return map;
}
/**
* 判断文件的类型:图片、视频、word。。。返回路径
*
* @param suffix 后缀名
* @return
*/
public Map<String, Object> filePath(String suffix, FileModel model) {
Map<String, Object> map = new HashMap<String, Object>();
String filePath = "";
String fileType = "";
if (suffix.equals("jpg") || suffix.equals("png")) {
fileType = "images";
} else if (suffix.equals("mov")) {
fileType = "mov";
} else if (suffix.equals("mp4")) {
fileType = "mp4";
} else if (suffix.equals("xlsx") || suffix.equals("xls")) {
fileType = "excel";
} else if (suffix.equals("pdf")) {
fileType = "pdf";
} else if (suffix.equals("ppt") || suffix.equals("pptx")) {
fileType = "ppt";
} else if (suffix.equals("doc") || suffix.equals("docx")) {
fileType = "word";
} else {
fileType = "other";
}
filePath = model.getUploadPath() + fileType;
map.put("filePath", filePath);
map.put("fileType", fileType);
return map;
}
public int getTypeByUrl(String suffix) {
suffix = suffix.toLowerCase().trim();
if (!"jpg".equals(suffix) && !"png".equals(suffix)) {
if ("mov".equals(suffix) || "mp4".equals(suffix)) {
return 0;
} else {
return 1;
}
}
return 2;
}
}
package com.ifknow.utils;
/**
* @Author: ifknow
* @Date: 2020/8/25 10:00
* @Description: NO Description
*/
public class FileModel {
private String uploadPath;
private String readPath;
public String getUploadPath() {
return uploadPath;
}
public FileModel setUploadPath(String uploadPath) {
this.uploadPath = uploadPath;
return this;
}
public String getReadPath() {
return readPath;
}
public FileModel setReadPath(String readPath) {
this.readPath = readPath;
return this;
}
}
package com.ifknow.controller;
import com.ifknow.config.ObtainProperties;
import com.ifknow.utils.FileModel;
import com.ifknow.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: ifknow
* @Date: 2020/8/25 9:59
* @Description: NO Description
*/
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/file")
public class FileUploadController {
@Autowired
private ObtainProperties obtainProperties;
@PostMapping("/upload")
public Map<String, Object> upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
FileModel model = new FileModel().setUploadPath(obtainProperties.getUploadFile().getUploadPath()).setReadPath(obtainProperties.getUploadFile().getReadPath());
FileUtil uploadUtil = new FileUtil();
Map<String, Object> map = uploadUtil.upload(file, request, model);
log.info(file.getOriginalFilename() + " 上传成功");
return map;
}
}
打开浏览器访问 http://localhost:8081/index.html
选择文件后,可看到效果,接口返回的文件信息,在实际的开发中可用于图片回显等业务需求。
本文中暂未考虑到异常处理,可以自己了解。方案:可以使用@RestControllerAdcvice。
示例代码-GitHub
示例代码-Gitee
个人博客-ifknow