文件上传的流程,相当于是复制,是读取了要上传文件的二进制流,并把这个二进制流的信息复制给服务器指定路径的另一个文件
在服务器中需要有专门的目录来存放上传路径 ,在新的上传请求传来时,必应判断该上传路径是否存在,若不存在 ,则需要先创建该上传目录。
在服务器中的文件,为了防止上传文件的名称重复(防止重复提交同一文件),从而产生冲突等问题,应用 UUID 来生成随机 ID 为新文件命名
文件上传应当将上传至服务器的url地址保存在数据库中
在前端向后端发起上传请求时,传参中必然带有文件信息,此时在 Controller 层对应的接口中会接收到 MultipartFile 类型的 file
通过以下代码可获取原文件的信息:
//原文件名称
String OriginFileName = file.getOriginalFilename();
//原文件文件名最大长度
int fileNamelength = file.getOriginalFilename().length()
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file)
{
String fileName = file.getOriginalFilename();
//获得文件名后缀
String extension = getExtension(file);
//拼接上时间
fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
return fileName;
}
为什么要拼接上时间,是因为window类似mysql也有自己的索引规则,通过时间来查找,能减轻搜索压力
假设,存放新文件的变量名称为 newFile ,远程文件变量名称为 oldFile
则可通过以下代码将远程文件保存至本地文件中:
oldFile.transferTo(newFile);
upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
其中DEFAULT_ALLOWED_EXTENSION是上传时候默认携带的一个参数,存储了一个集合(文件类型)

可以发现这里面没有视频的类型,要想该上传可以通过视频类型的文件,可以在这个集合上加上视频对应的类型

前端采取ElementUI上传的组件
这个项目上传是需要验证权限的,所以请求时候在请求头携带了一个认证的参数
将文件拖到此处,或点击上传
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
后端
CommonController
这里处理上传后的文件名称和请求路径进行一个拼接
public class CommonController {
@Autowired
private ServerConfig serverConfig;
/**
* 通用上传请求
*/
@PostMapping("/upload")
public ResultJson uploadFile(MultipartFile file) throws Exception {
try {
// 上传文件路径(配置文件中的)
String filePath = NiuaConfig.getUploadPath();
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
//获取请求路径
String url = serverConfig.getUrl() + fileName;//http://127.0.0.1:9527
Map<String, String> prams = new HashMap<String, String>();
prams.put("fileName", fileName);
//profile/upload/2022/07/28/94ac7ece-3371-40fb-80d0-8f42231df2f7.jpg
prams.put("url", url);
//http://127.0.0.1:9527/profile/upload/2022/07/28/94ac7ece-3371-40fb-80d0-8f42231df2f7.jpg
return ResultJson.ok(prams);
} catch (Exception e) {
return ResultJson.failure(ResultCode.BAD_REQUEST, e.getMessage());
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
获取新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
- 1
根据文件路径上传,这里携带了DEFAULT_ALLOWED_EXTENSION参数,表示默认文件上传的类型
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
文件上传
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
//文件大小检验
int fileNamelength = file.getOriginalFilename().length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
//文件类型检验
assertAllowed(file, allowedExtension);
//获取拼接说时间的文件名称(编码新文件名)
String fileName = extractFilename(file);
//返回一个文件的绝对路径
File desc = getAbsoluteFile(baseDir, fileName);
//把远程文件存入本地
file.transferTo(desc);
String pathFileName = getPathFileName(baseDir, fileName);
return pathFileName;//profile/upload/2022/07/28/94ac7ece-3371-40fb-80d0-8f42231df2f7.jpg
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
返回的数据格式ResultJson.java
package tech.niua.common.model;
import lombok.Data;
import java.io.Serializable;
/**
* @author Wangzhen
* RESTful API 返回类型
* createAt: 2020/5/29
*/
@Data
public class ResultJson<T> implements Serializable{
private static final long serialVersionUID = 783015033603078674L;
private int code;
private String msg;
private T data;
public static ResultJson ok() {
return ok("");
}
public static ResultJson ok(Object o) {
return new ResultJson(ResultCode.SUCCESS, o);
}
public static ResultJson failure(ResultCode code) {
return failure(code, "");
}
public static ResultJson failure(ResultCode code, Object o) {
return new ResultJson(code, o);
}
public ResultJson(ResultCode resultCode) {
setResultCode(resultCode);
}
public ResultJson(ResultCode resultCode, T data) {
setResultCode(resultCode);
this.data = data;
}
public void setResultCode(ResultCode resultCode) {
this.code = resultCode.getCode();
this.msg = resultCode.getMsg();
}
@Override
public String toString() {
return "{" +
"\"code\":" + code +
", \"msg\":\"" + msg + '\"' +
", \"data\":\"" + data + '\"'+
'}';
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
返回的数据格式ResultJson.java
package tech.niua.common.model;
import lombok.Data;
import java.io.Serializable;
/**
* @author Wangzhen
* RESTful API 返回类型
* createAt: 2020/5/29
*/
@Data
public class ResultJson<T> implements Serializable{
private static final long serialVersionUID = 783015033603078674L;
private int code;
private String msg;
private T data;
public static ResultJson ok() {
return ok("");
}
public static ResultJson ok(Object o) {
return new ResultJson(ResultCode.SUCCESS, o);
}
public static ResultJson failure(ResultCode code) {
return failure(code, "");
}
public static ResultJson failure(ResultCode code, Object o) {
return new ResultJson(code, o);
}
public ResultJson(ResultCode resultCode) {
setResultCode(resultCode);
}
public ResultJson(ResultCode resultCode, T data) {
setResultCode(resultCode);
this.data = data;
}
public void setResultCode(ResultCode resultCode) {
this.code = resultCode.getCode();
this.msg = resultCode.getMsg();
}
@Override
public String toString() {
return "{" +
"\"code\":" + code +
", \"msg\":\"" + msg + '\"' +
", \"data\":\"" + data + '\"'+
'}';
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
返回的数据格式ResultJson.java
package tech.niua.common.model;
import lombok.Data;
import java.io.Serializable;
/**
* @author Wangzhen
* RESTful API 返回类型
* createAt: 2020/5/29
*/
@Data
public class ResultJson<T> implements Serializable{
private static final long serialVersionUID = 783015033603078674L;
private int code;
private String msg;
private T data;
public static ResultJson ok() {
return ok("");
}
public static ResultJson ok(Object o) {
return new ResultJson(ResultCode.SUCCESS, o);
}
public static ResultJson failure(ResultCode code) {
return failure(code, "");
}
public static ResultJson failure(ResultCode code, Object o) {
return new ResultJson(code, o);
}
public ResultJson(ResultCode resultCode) {
setResultCode(resultCode);
}
public ResultJson(ResultCode resultCode, T data) {
setResultCode(resultCode);
this.data = data;
}
public void setResultCode(ResultCode resultCode) {
this.code = resultCode.getCode();
this.msg = resultCode.getMsg();
}
@Override
public String toString() {
return "{" +
"\"code\":" + code +
", \"msg\":\"" + msg + '\"' +
", \"data\":\"" + data + '\"'+
'}';
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
编码新文件名
通过UUID(避免重复)给文件编码新的文件名,并且按照指定的样式返回
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file)
{
String fileName = file.getOriginalFilename();
//获得文件名后缀
String extension = getExtension(file);
//拼接上时间
fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
return fileName;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
上传成功效果图
