Pre Merge pull request !741 from 秋辞未寒/dev

This commit is contained in:
秋辞未寒 2025-08-12 08:19:51 +00:00 committed by Gitee
commit 2e66a545e0
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
3 changed files with 59 additions and 1 deletions

View File

@ -2,6 +2,8 @@ package org.dromara.system.controller.system;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.QueryGroup;
@ -18,9 +20,11 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import java.io.IOException;
import java.util.Arrays;
@ -92,6 +96,19 @@ public class SysOssController extends BaseController {
ossService.download(ossId, response);
}
/**
* 下载OSS对象使用非阻塞流方式
*
* @param ossId OSS对象ID
*/
@SaIgnore
@GetMapping("/streaming/download/{ossId}")
public ResponseEntity<StreamingResponseBody> download(@PathVariable Long ossId) {
// 该方法是异步处理方法 SaToken 的权限注解不支持异步与同步混用会报异常但不影响正常的下载此处手动校验即可
StpUtil.checkPermission("system:oss:download");
return ossService.streamingDownload(ossId);
}
/**
* 删除OSS对象存储
*

View File

@ -5,7 +5,9 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.bo.SysOssBo;
import org.dromara.system.domain.vo.SysOssVo;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import java.io.File;
import java.io.IOException;
@ -68,6 +70,13 @@ public interface ISysOssService {
*/
void download(Long ossId, HttpServletResponse response) throws IOException;
/**
* 非阻塞流下载方法
*
* @param ossId OSS对象ID
*/
ResponseEntity<StreamingResponseBody> streamingDownload(Long ossId);
/**
* 删除OSS对象存储
*

View File

@ -21,6 +21,7 @@ import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.core.WriteOutSubscriber;
import org.dromara.common.oss.entity.UploadResult;
import org.dromara.common.oss.enums.AccessPolicyType;
import org.dromara.common.oss.factory.OssFactory;
@ -32,12 +33,16 @@ import org.dromara.system.mapper.SysOssMapper;
import org.dromara.system.service.ISysOssService;
import org.jetbrains.annotations.NotNull;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
@ -183,6 +188,33 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
storage.download(sysOss.getFileName(), response.getOutputStream(), response::setContentLengthLong);
}
/**
* 非阻塞流下载方法
*
* @param ossId OSS对象ID
*/
@Override
public ResponseEntity<StreamingResponseBody> streamingDownload(Long ossId) {
SysOssVo sysOss = SpringUtils.getAopProxy(this).getById(ossId);
if (ObjectUtil.isNull(sysOss)) {
throw new ServiceException("文件数据不存在!");
}
OssClient storage = OssFactory.instance(sysOss.getService());
// 构建响应体
String percentEncodedFileName = FileUtils.percentEncode(sysOss.getOriginalName());
String contentDispositionValue = "attachment; filename=%s;filename*=utf-8''%s".formatted(percentEncodedFileName, percentEncodedFileName);
ResponseEntity.BodyBuilder bodyBuilder = ResponseEntity.ok()
.header(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "Content-Disposition,download-filename")
.header(HttpHeaders.CONTENT_DISPOSITION, contentDispositionValue)
.header("download-filename", percentEncodedFileName)
.contentType(MediaType.APPLICATION_OCTET_STREAM);
// 获取写出流订阅器
WriteOutSubscriber<OutputStream> subscriber = storage.download(sysOss.getFileName(), bodyBuilder::contentLength);
return bodyBuilder.body(subscriber::writeTo);
}
/**
* 上传 MultipartFile 到对象存储服务并保存文件信息到数据库
*
@ -197,7 +229,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
OssClient storage = OssFactory.instance();
UploadResult uploadResult;
try {
uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType());
uploadResult = storage.uploadSuffix(file.getInputStream(), suffix, file.getSize(), file.getContentType());
} catch (IOException e) {
throw new ServiceException(e.getMessage());
}