文件上传原创
# 后端
# CosManager.java
/**
* 上传对象
*
* @param key 唯一键
* @param file 文件
*/
public void putObject(String key, File file) {
// 调用 COS 接口之前必须保证本进程存在一个 COSClient 实例,如果没有则创建
COSClient cosClient = createCOSClient();
PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key,
file);
cosClient.putObject(putObjectRequest);
// 确认本进程不再使用 cosClient 实例之后,关闭即可
cosClient.shutdown();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# CosController
import cn.hutool.core.io.FileUtil;
import com.hccake.ballcat.codegen.config.CosManager;
import com.hccake.ballcat.codegen.exception.BaseResponse;
import com.hccake.ballcat.codegen.exception.BusinessException;
import com.hccake.ballcat.codegen.exception.ErrorCode;
import com.hccake.ballcat.codegen.exception.ResultUtils;
import com.hccake.ballcat.codegen.model.entity.User;
import com.hccake.ballcat.codegen.model.enums.FileUploadBizEnum;
import com.hccake.ballcat.codegen.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Arrays;
import java.util.Date;
/**
* cos对象操作
*
*/
@RestController
@RequestMapping("/cos")
@Slf4j
@Tag(name = "CosController")
public class CosController {
@Resource
private UserService userService;
@Resource
private CosManager cosManager;
/**文件上传
*
* @param multipartFile
* @param biz
* @param request
* @return
*/
@Operation(summary = "文件上传")
@Parameter(name="biz",description = "cos文件地址,可选user,file",required = true)
@PostMapping("/upload")
public BaseResponse<String> upload(@RequestPart("file") MultipartFile multipartFile, String biz, HttpServletRequest request) {
FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz);
if (fileUploadBizEnum == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
validFile(multipartFile, fileUploadBizEnum);
User loginUser = userService.getLoginUser(request);
// 文件目录:根据业务、用户来划分
Date now = new Date();
long timestamp = now.getTime();
String uuid = RandomStringUtils.randomAlphanumeric(8);
String filename = uuid + "-" + timestamp;
String fileSuffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
String filepath = String.format("/%s/%s/%s.%s", fileUploadBizEnum.getValue(), loginUser.getId(), filename, fileSuffix);
File file = null;
try {
// 上传文件
file = File.createTempFile(filepath, null);
multipartFile.transferTo(file);
cosManager.putObject(filepath, file);
// 返回可访问地址
String HOST = "https://img.xiaoying.org.cn";
return ResultUtils.success(HOST + filepath);
} catch (Exception e) {
log.error("file upload error, filepath = " + filepath, e);
throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败");
} finally {
if (file != null) {
// 删除临时文件
boolean delete = file.delete();
if (!delete) {
log.error("file delete error, filepath = {}", filepath);
}
}
}
}
/**
* 校验文件
*
* @param multipartFile
* @param fileUploadBizEnum 业务类型
*/
private void validFile(MultipartFile multipartFile, FileUploadBizEnum fileUploadBizEnum) {
// 文件大小
long fileSize = multipartFile.getSize();
// 文件后缀
String fileSuffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
final long ONE_M = 1024 * 1024L;
final long ONE_F = 300 * 1024 * 1024L;
if (FileUploadBizEnum.USER_AVATAR.equals(fileUploadBizEnum)) {
if (!Arrays.asList("jpeg", "jpg", "svg", "png", "webp").contains(fileSuffix)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "图片类型错误,只能上传jpeg,jpg,svg,png,webp格式");
}
if (fileSize > ONE_M) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "图片大小不能超过 1M");
}
}
if (FileUploadBizEnum.FILE_UPLOAD.equals(fileUploadBizEnum)) {
if (fileSize > ONE_F) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件大小不能超过 300M");
}
if (!Arrays.asList("jpeg", "jpg", "svg", "png", "webp").contains(fileSuffix)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件类型错误");
}
}
}
}
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# 前端
基于vue3 + ts + elementplus
# 接口
/**
* 上传文件
*
* @param file
*/
export function uploadFileApi(file: File): AxiosPromise<FileInfo> {
const formData = new FormData();
formData.append('file', file);
formData.append('biz', 'user_avatar');
return request({
url: '/api/file/upload',
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 使用
html
<el-form-item label="上传头像" :label-width="formLabelWidth">
<el-upload
class="upload-demo"
drag
:show-file-list= false
action=""
:http-request="upload"
:before-upload="beforeUpload"
>
<el-icon size=100 class="el-upload-icon" v-if="!flag"><upload-filled /></el-icon>
<div class="el-upload__text" v-if="!flag">
拖拽或 <em>点击上传</em>
</div>
<img :src="imgUrl" v-if="flag" class="imgUrl" />
<template #tip>
<div class="el-upload__tip">
jpg/png files with a size less than 500kb
</div>
</template>
</el-upload>
</el-form-item>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ts
const files = ref('')
function beforeUpload(file: any) {
const timeStamp = new Date().getTime()
const fileExtension = file.name.split('.').pop().toLowerCase()
const copyFile = new File([file], `${timeStamp}` + '.' + fileExtension)
files.value = copyFile
}
const form = ref<UserUpdateMyRequest>({
userAvatar: ''
})
async function upload() {
await uploadFileApi(files.value).then((res) => {
form.value.userAvatar = res.data
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
上次更新: 2024/02/04 10:50:57
- 01
- element-plus多文件手动上传 原创11-03
- 02
- TrueLicense 创建及安装证书 原创10-25
- 03
- 手动修改迅捷配置 原创09-03
- 04
- 安装 acme.sh 原创08-29
- 05
- zabbix部署 原创08-20