ruoyi 文件上传下载功能


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 下载功能
public void downloadTemplate(HttpServletResponse response){
try {
//从resources 资源目录获取文件
ClassPathResource classPathResource = new ClassPathResource(uploadTemplateXlsx);
InputStream inputStream = classPathResource.getInputStream();
response.setContentType("application/x-download");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("template.xlsx", "UTF-8"));
try (ServletOutputStream out = response.getOutputStream();
InputStream stream = inputStream) {
byte buff[] = new byte[1024];
int length;
// 从文件输入流读取数据,并写入响应输出流中,实现文件下载
while ((length = stream.read(buff)) > 0) {
out.write(buff, 0, length);
}
out.flush(); // 刷新输出流,确保所有数据都被发送到客户端
}catch (Exception ex){
ex.printStackTrace(); //
}
}catch (Exception ex){
ex.printStackTrace(); //
}
}

若依框架常规下载实现

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
package com.ruoyi.web.controller.system;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SysFileUpload;
import com.ruoyi.system.service.ISysFileUploadService;
import org.springframework.web.multipart.MultipartFile;


@RestController
@RequestMapping("/system/fileupload")
public class SysFileUploadController extends BaseController
{
@Autowired
private ISysFileUploadService sysFileUploadService;

// 文件上传通过 FileUploadUtils.upload 去存储解析
@ApiOperation("文件上传")
@Log(title = "文件上传记录", businessType = BusinessType.EXPORT)
@PostMapping("/uploadImage")
public AjaxResult fileUpload(@RequestParam("file")MultipartFile file){
SysFileUpload sysFileUpload = new SysFileUpload();
try {
String uploadPath = FileUploadUtils.upload(RuoYiConfig.getUploadPath(), file);
}catch (Exception e){
logger.error("上传文件异常", e);
throw new RuntimeException(e);
}
return success(sysFileUpload);
}
// 直接下载
@ApiOperation("文件下载")
@GetMapping("/download")
public ResponseEntity<FileSystemResource> downloadFile(Long fileId){
try {
SysFileUpload sysFileUpload = sysFileUploadService.selectSysFileUploadById(fileId);
String uploadPath = sysFileUpload.getFilePath().replace("/profile", RuoYiConfig.getProfile());
FileSystemResource resource = new FileSystemResource(uploadPath);
// 检查文件是否存在
if (!resource.exists()) {
throw new RuntimeException("文件未找到:" + sysFileUpload.getFileName());
}
// 设置HTTP头
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + resource.getFilename());
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
// 返回文件资源和HTTP头
return ResponseEntity.ok()
.headers(headers)
.body(resource);
}catch (Exception e){
logger.error("下载文件异常", e);
return ResponseEntity.badRequest().body(null);
}
}
// 用于前端展示的下载方式
@GetMapping("/downloadFileShow")
public ResponseEntity<FileSystemResource> downloadFileShow(Long fileId){
try {
SysFileUpload sysFileUpload = sysFileUploadService.selectSysFileUploadById(fileId);
String uploadPath = sysFileUpload.getFilePath().replace("/profile", RuoYiConfig.getProfile());
FileSystemResource resource = new FileSystemResource(uploadPath);
// 检查文件是否存在
if (!resource.exists()) {
throw new RuntimeException("文件未找到:" + sysFileUpload.getFileName());
}
// 设置HTTP头
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + resource.getFilename());
headers.add(HttpHeaders.CONTENT_TYPE, sysFileUpload.getFileType());
// 返回文件资源和HTTP头
return ResponseEntity.ok()
.headers(headers)
.body(resource);
}catch (Exception e){
logger.error("下载文件异常", e);
return ResponseEntity.badRequest().body(null);
}
}
}

前端 需要携带 token 信息 去下载
使用 fetch 进行 http 请求 下面用a 标签去实现下载

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
async downloadsysconferenceTemplate(){
try {
let filename = "会议签到模板"+this.$dayjs(new Date).format("YYYYMMDDHHmmss")+".xlsx";
let url = this.baseUrl + "/system/conference/downloadSysConferenceTemplate";
// 发起fetch请求,注意添加credentials确保跨域时携带cookie
const response = await fetch(url, {
method: 'GET',
headers: new Headers({
'Authorization': getToken(), // 或者 'Token': token,根据后端要求调整
}),
credentials: 'include', // 或 'include',根据实际情况选择
});

// 检查响应状态
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// // 获取文件blob数据
const blob = await response.blob();
// 需要设置文件类型 采用下
//const arrayBuffer = await response.arrayBuffer();
//const repblob = new Blob([arrayBuffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
// // 创建URL表示 Blob 对象
const urlForBlob = window.URL.createObjectURL(blob);
// 创建隐藏的a标签并触发点击下载
const link = document.createElement('a');
link.href = urlForBlob;
link.download = filename; // 指定下载的文件名
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

// 释放URL对象
window.URL.revokeObjectURL(urlForBlob);
} catch (error) {
console.error('Download failed:', error);
}
}

基于上面方法修改为通用方法, Vue 注入

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
在 mian.js 添加方法
// 添加 downloadTemplate
import { download, downloadTemplate } from '@/utils/request'
// 挂载全局方法
Vue.prototype.downloadTemplate = downloadTemplate
export async function downloadTemplate(url, usePostMethod, data, filename){
try {
const method = usePostMethod ? 'POST' : 'GET';
const body = usePostMethod ? JSON.stringify(data) : undefined;
const headers = new Headers({
'Content-Type': 'application/json',
'Authorization': getToken(), // 或者 'Token': token,根据后端要求调整
});
// 发起fetch请求,注意添加credentials确保跨域时携带cookie
const response = await fetch(url, {
method,
headers,
body,
credentials: 'include', // 或 'include',根据实际情况选择
});

// 检查响应状态
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// // 获取文件blob数据
const blob = await response.blob();
// // 创建URL表示 Blob 对象
const urlForBlob = window.URL.createObjectURL(blob);
// 创建隐藏的a标签并触发点击下载
const link = document.createElement('a');
link.href = urlForBlob;
link.download = filename; // 指定下载的文件名
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

// 释放URL对象
window.URL.revokeObjectURL(urlForBlob);
} catch (error) {
console.error('Download failed:', error);
}
}

常规不需要token的文件下载方式 一种通过 a 标签 下载 一种通过 iframe 下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
downloadSysConferenceTemplate(){
let a = document.createElement("a");
a.setAttribute("href", this.baseURL+"/system/conference/downloadSysConferenceTemplate");
a.setAttribute("target", "_blank");
a.style.display = 'none'
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
downloadSysConferenceTemplate(){
const iframe = document.createElement("iframe");
iframe.setAttribute("hidden","hidden");
document.body.appendChild(iframe);
iframe.onload = () => {
if(iframe){
iframe.setAttribute('src','about:blank');
}
};
let url = this.baseURL + "/system/conference/downloadSysConferenceTemplate";
iframe.setAttribute("src",url);
}