SpringBoot文件上传和下载

koopkl Lv2

环境

  • SpringBoot: 2.5.14
  • Vue3: ^3.2.47
  • element-plus: ^2.3.4,
  • **axios:**^1.4.0,

代码

后端

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
@PostMapping("/upload")
public R uploadFile(@RequestParam(value = "file") MultipartFile[] files,
@Value("${file.server.resource-location}") String filePath) {
// 这里允许上传多个文件
for (MultipartFile file: files) {
// 首先判断文件是否存在
if (file == null || file.isEmpty()) {
continue;
}
try {
// 本地文件保存位置
File uploadDir = new File(filePath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
log.info(uploadDir.getAbsolutePath());
String fileName = file.getOriginalFilename();
if (fileName != null) {
// uuid 文件名工具类方法
String uniqueFileName = ProposalUtil.getUniqueFileID(fileName);
String fileFullPath = uploadDir.getAbsolutePath() + File.separator + uniqueFileName;
File localFile = new File(fileFullPath);
// transfer to local
file.transferTo(localFile);

}
} catch (Exception e) {
log.error("文件上传失败:" + file.getOriginalFilename());
}
}
// R为后端返回值封装类
return R.ok();
}

@GetMapping("/download")
public void downloadFile(@RequestParam(value = "file") String fileName,
@Value("${file.server.resource-location}") String filePath,
HttpServletResponse response) throws IOException {
response.reset();
response.setContentType("application/octet-stream");
String encoded = URLEncoder.encode(fileName, "UTF-8");
// 解决中文文件名乱码问题,必须要对文件名进行utf-8编码
response.setHeader("Content-disposition",
"attachment;filename=" + encoded + ";filename*=UTF-8" + encoded);
// 这里使用原生response会失去Springboot的config,需要手动配置一下跨域
response.setHeader("Access-Control-Allow-Origin", "*");
// 从文件读到servlet response输出流中

File fileDir = new File(filePath);
// 默认文件名是带扩展名的!!!
File file = new File(fileDir.getAbsoluteFile() + File.separator + fileName);
try (FileInputStream inputStream = new FileInputStream(file)) {
byte[] b = new byte[1024];
int len;
while ((len = inputStream.read(b)) > 0) {
response.getOutputStream().write(b, 0, len);
}
log.info("File downloaded successfully: " + fileDir.getAbsoluteFile() + File.separator + fileName );
} catch (IOException e) {
if (e instanceof FileNotFoundException) {
// 设置返回值为500
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
log.error("File not found: " + fileDir.getAbsoluteFile() + File.separator + fileName );
}
}
}

前端

部分样式可能不合理可以自行调正

上传

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

<template>
<div class='file'>
<el-upload
v-model:file-list="fileList"
drag
ref="uploadRef"
:accept = 'acceptFile'
:multiple="true"
:action="uploadUrl"
:auto-upload="false"
:limit="5"
:on-success="uploadSuccess"
:on-error="uploadError"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:before-upload="checkUpload"
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">
Drop file here or <em>click to upload</em>
</div>
<template #tip>
<div class="el-upload__tip">
请上传.json文件
</div>
</template>

</el-upload>
<el-button class="ml-3" type="success" @click="submitUpload">
upload to server
</el-button>
</div>
</template>

<script setup>
import {ElButton, ElUpload, ElIcon, ElMessage} from 'element-plus'
import { ref } from 'vue'
import { fileUploadUrl } from "@/api";
const uploadRef = ref()
// 上传接口地址
const uploadUrl = ref("http://127.0.0.1:6666/upload")
const fileList = ref([])
// 选择文件时会自动过滤掉不属于acceptFile列表内的文件,但无法阻止上传不符合要求的文件。
// 所以下面需要一个checkUpload方法来手动检查文件类型。
// 多个文类型需要用,分割,如: '.json,pdf,.csv'
const acceptFile = ref('.json')

const uploadSuccess = (response, uploadFile) => {
// 上传成功
console.log("res")
console.log(response)
console.log("file:")
console.log(uploadFile)
console.log(fileList.value)
}

const uploadError = (response,uploadFile) => {
// 上传失败调用方法
console.log("res")
console.log(response)
console.log("file:")
console.log(uploadFile)

}
const handleRemove = (file, uploadFiles)=> {
// 删除当前文件列表方法
console.log(file, uploadFiles)
}
const handleExceed = (files, uploadFiles) => {
// 文件超出规定限制时输出
ElMessage.warning(
`The limit is 5, you selected ${files.length} files this time, add up to ${
files.length + uploadFiles.length
} totally`
)
}

const checkUpload = (file) => {
console.log(file)
const types = [
// 添加其他格式文件请查询MIME
// json
'application/json',
]
if(types.indexOf(file.type) === -1) {
ElMessage.warning(
'请上传格式正确的文件'
)
}
}
// 不自动上传,点击上传按钮后,调用el-upload的submit来进行上传
const submitUpload = () => {
uploadRef.value.submit()
}


</script>

<style scoped lang='less'>
.form {
margin: 50px 0 0 0;
}
.file {
margin-top: 30px;
}
</style>

下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<el-link type="primary"
:underline="false"
@click="downloadFile">{{fileName}}</el-link>
</template>


<script setup>
import { ElMessage, ElLink } from "element-plus";
const fileName = ref("testJson.json")
const downloadFile = () => {
download(infoP.file_name).then((response) => {
console.log(response)
const blob = new Blob([response.data], { type: 'application/octet-stream' })
const link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = fileName.value
link.click()
}).catch(error => {
ElMessage.error('文件不存在')
})
}
</script>
  • Title: SpringBoot文件上传和下载
  • Author: koopkl
  • Created at : 2024-04-09 14:01:44
  • Updated at : 2024-04-09 14:17:04
  • Link: https://lime.popla.cc/2024/04/09/文件上传和下载/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
SpringBoot文件上传和下载