Commit 779f5d7b by zhangxingmin

Merge remote-tracking branch 'origin/test' into dev

parents ecd8f9fb 93c23a0c
# 构建阶段 - 创建包含LibreOffice的基础镜像
FROM openjdk:8-jre-slim as base-builder
# ============================================================
# 构建阶段 - 创建包含 LibreOffice 的基础镜像
# ============================================================
FROM eclipse-temurin:8-jre-jammy as base-builder
ENV LANG=zh_CN.UTF-8 \
LANGUAGE=zh_CN:zh \
LC_ALL=zh_CN.UTF-8 \
DEBIAN_FRONTEND=noninteractive
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && \
sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list
# 替换为阿里云 Ubuntu 源(jammy = 22.04)
RUN sed -i 's|archive.ubuntu.com|mirrors.aliyun.com|g' /etc/apt/sources.list && \
sed -i 's|security.ubuntu.com|mirrors.aliyun.com|g' /etc/apt/sources.list
# 安装字体、LibreOffice 及中文语言包
RUN apt-get update && \
apt-get install -y --no-install-recommends \
fonts-liberation \
......@@ -29,12 +33,15 @@ RUN apt-get update && \
RUN mkdir -p /home/app
WORKDIR /home/app
# ============================================================
# 最终阶段
# ============================================================
FROM base-builder
# 只拷贝jar包
# 拷贝 Spring Boot 可执行 JAR
COPY target/yd-oss-api-1.0-SNAPSHOT-exec.jar /home/app/yd-oss-api.jar
# 执行命令启动jar,并设置JVM内存参数
# 启动命令,设置 JVM 内存参数
ENTRYPOINT ["java", "-Xmx1024m", "-Xms512m", "-jar", "/home/app/yd-oss-api.jar"]
EXPOSE 9106
\ No newline at end of file
package com.yd.oss.api.config;
import org.jodconverter.core.office.OfficeManager;
import org.jodconverter.local.office.LocalOfficeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
public class OfficeManagerHolder {
private static final Logger logger = LoggerFactory.getLogger(OfficeManagerHolder.class);
private static OfficeManager instance = null;
private static final Object lock = new Object();
public static OfficeManager getInstance(String libreOfficeHome) throws Exception {
if (instance == null) {
synchronized (lock) {
if (instance == null) {
logger.info("正在启动 LibreOffice (home: {}) ...", libreOfficeHome);
instance = LocalOfficeManager.builder()
.officeHome(new File(libreOfficeHome))
.build();
instance.start();
logger.info("LibreOffice 启动成功");
}
}
}
return instance;
}
public static void stop() {
if (instance != null) {
try {
instance.stop();
logger.info("LibreOffice 已停止");
} catch (Exception e) {
logger.error("停止 LibreOffice 失败", e);
}
instance = null;
}
}
}
\ No newline at end of file
package com.yd.oss.api.controller;
import com.yd.common.result.Result;
import com.yd.oss.api.service.ApiChunkedUploadContextService;
import com.yd.oss.feign.client.ApiChunkedUploadContextFeignClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.Map;
/**
* 分片上传上下文信息
* (一个任务上传文件信息拆分成多个ETag上传存储,任务执行完毕,阿里云合并ETag列表为完整的文件信息)
* @author zxm
* @since 2026-08-05
*/
@Slf4j
@RestController
@RequestMapping("/chunkedUploadContext")
@Validated
public class ApiChunkedUploadContextController implements ApiChunkedUploadContextFeignClient {
@Resource
private ApiChunkedUploadContextService apiChunkedUploadContextService;
/**
* 上传单个分片
* @param chunk
* @param taskId
* @param chunkIndex
* @param projectBizId
* @param source
* @return
*/
@Override
public Result<Void> uploadChunk(MultipartFile chunk, String taskId, Integer chunkIndex, String projectBizId, String source) {
apiChunkedUploadContextService.uploadChunk(taskId, chunkIndex, chunk,projectBizId,source);
return Result.success();
}
/**
* 完成分片上传(合并)
*/
public Result<Map<String, Object>> finishChunks(String taskId,
String projectBizId) {
return apiChunkedUploadContextService.finishChunks(taskId,projectBizId);
}
}
package com.yd.oss.api.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yd.common.result.Result;
import com.yd.oss.api.service.ApiOssService;
import com.yd.oss.feign.client.ApiOssFeignClient;
......@@ -7,9 +8,13 @@ import com.yd.oss.feign.request.ApiUploadFileRequest;
import com.yd.oss.feign.response.ApiBatchUploadResponse;
import com.yd.oss.feign.response.ApiFileMetadataResponse;
import com.yd.oss.feign.response.ApiUploadResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
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;
......@@ -21,6 +26,7 @@ import java.util.List;
* @author zxm
* @since 2025-07-31
*/
@Slf4j
@RestController
@RequestMapping("/oss")
@Validated
......@@ -29,6 +35,9 @@ public class ApiOssController implements ApiOssFeignClient {
@Autowired
private ApiOssService apiOssService;
@Autowired
private ObjectMapper objectMapper;
/**
* 上传文件
* @param file 上传的文件
......@@ -50,6 +59,17 @@ public class ApiOssController implements ApiOssFeignClient {
return apiOssService.uploadFileBody(file,request);
}
public Result<ApiUploadResponse> uploadFileBodyWithJson(MultipartFile file,String requestJson) {
try {
// 反序列化 JSON 为 ApiUploadFileRequest
ApiUploadFileRequest request = objectMapper.readValue(requestJson, ApiUploadFileRequest.class);
return apiOssService.uploadFileBody(file, request);
} catch (Exception e) {
log.error("解析请求参数失败", e);
return Result.fail("请求参数格式错误");
}
}
/**
* 下载文件
* @param fileKey 文件唯一标识
......
package com.yd.oss.api.controller;
import com.yd.oss.api.utils.LocalDocumentConversionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* 文档转换接口
* 提供将 Office 文档(Word/Excel/PPT)转换为 PDF/HTML/图片等格式的 HTTP 接口。
* 供其他微服务通过内网调用。
*/
@RestController
@RequestMapping("/convert")
public class DocumentConvertController {
private static final Logger logger = LoggerFactory.getLogger(DocumentConvertController.class);
@Autowired
private LocalDocumentConversionService conversionService;
/**
* 将指定 URL 的文档转换为目标格式,并返回字节流。
*
* @param fileUrl 源文件 URL(支持 HTTP/HTTPS/OSS)
* @param targetFormat 目标格式,如 pdf、html、png、jpg 等,默认 pdf
* @return 转换后的文件字节流,Content-Type 根据格式自动设置
*/
@PostMapping("/file")
public ResponseEntity<byte[]> convert(
@RequestParam("fileUrl") String fileUrl,
@RequestParam(value = "targetFormat", defaultValue = "pdf") String targetFormat) {
logger.info("收到转换请求: fileUrl={}, targetFormat={}", fileUrl, targetFormat);
try {
byte[] result = conversionService.convertToBytes(fileUrl, targetFormat);
HttpHeaders headers = new HttpHeaders();
// 根据目标格式设置 Content-Type
MediaType mediaType = getMediaType(targetFormat);
headers.setContentType(mediaType);
// 可选:设置下载文件名
String filename = extractFileName(fileUrl) + "." + targetFormat;
try {
headers.setContentDispositionFormData("attachment",
URLEncoder.encode(filename, StandardCharsets.UTF_8.name()));
} catch (UnsupportedEncodingException e) {
// 忽略
}
logger.info("转换成功,返回字节数: {}", result.length);
return new ResponseEntity<>(result, headers, HttpStatus.OK);
} catch (Exception e) {
logger.error("文档转换失败: fileUrl={}, targetFormat={}", fileUrl, targetFormat, e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(("转换失败: " + e.getMessage()).getBytes(StandardCharsets.UTF_8));
}
}
private MediaType getMediaType(String format) {
if (format == null) return MediaType.APPLICATION_OCTET_STREAM;
switch (format.toLowerCase()) {
case "pdf":
return MediaType.APPLICATION_PDF;
case "html":
return MediaType.TEXT_HTML;
case "png":
return MediaType.IMAGE_PNG;
case "jpg":
case "jpeg":
return MediaType.IMAGE_JPEG;
default:
return MediaType.APPLICATION_OCTET_STREAM;
}
}
private String extractFileName(String url) {
if (url == null) return "converted";
int lastSlash = url.lastIndexOf('/');
if (lastSlash >= 0 && lastSlash < url.length() - 1) {
String name = url.substring(lastSlash + 1);
int dot = name.lastIndexOf('.');
return dot > 0 ? name.substring(0, dot) : name;
}
return "converted";
}
}
\ No newline at end of file
package com.yd.oss.api.service;
import com.yd.common.result.Result;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
public interface ApiChunkedUploadContextService {
void uploadChunk(String taskId, Integer chunkIndex, MultipartFile chunk,String projectBizId,String source);
Result<Map<String, Object>> finishChunks(String taskId,String projectBizId);
}
package com.yd.oss.api.utils;
import com.yd.oss.api.config.OfficeManagerHolder;
import org.jodconverter.core.DocumentConverter;
import org.jodconverter.core.office.OfficeException;
import org.jodconverter.local.LocalConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.UUID;
@Service
public class LocalDocumentConversionService {
private static final Logger logger = LoggerFactory.getLogger(LocalDocumentConversionService.class);
@Value("${jodconverter.libreoffice.home:}")
private String libreOfficeHome;
private DocumentConverter converter;
@PostConstruct
public void init() {
if (libreOfficeHome == null || libreOfficeHome.trim().isEmpty()) {
libreOfficeHome = System.getenv("LIBREOFFICE_HOME");
}
if (libreOfficeHome == null || libreOfficeHome.trim().isEmpty()) {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
libreOfficeHome = "D:/LibreOffice";
} else if (os.contains("linux")) {
libreOfficeHome = "/opt/libreoffice_standalone/libreoffice7.4";
} else if (os.contains("mac")) {
libreOfficeHome = "/Applications/LibreOffice.app/Contents";
} else {
throw new RuntimeException("无法确定 LibreOffice 安装路径,请通过配置或环境变量设置");
}
logger.warn("未配置 libreOfficeHome,使用默认路径: {}", libreOfficeHome);
}
try {
OfficeManagerHolder.getInstance(libreOfficeHome);
converter = LocalConverter.builder()
.officeManager(OfficeManagerHolder.getInstance(libreOfficeHome))
.build();
logger.info("JodConverter 初始化成功,LibreOffice 路径: {}", libreOfficeHome);
} catch (Exception e) {
logger.error("JodConverter 初始化失败,请检查 LibreOffice 安装", e);
throw new RuntimeException("JodConverter 初始化失败", e);
}
}
public byte[] convertToPdfBytes(String fileUrl) throws Exception {
return convertToBytes(fileUrl, "pdf");
}
public byte[] convertToBytes(String fileUrl, String targetExtension) throws Exception {
if (targetExtension.startsWith(".")) {
targetExtension = targetExtension.substring(1);
}
if (targetExtension == null || targetExtension.trim().isEmpty()) {
throw new IllegalArgumentException("目标扩展名不能为空");
}
logger.info("开始转换文档: {} -> 格式: {}", fileUrl, targetExtension);
Path tempInput = Files.createTempFile("convert_", "_" + UUID.randomUUID());
try (InputStream in = new URL(fileUrl).openStream()) {
Files.copy(in, tempInput, StandardCopyOption.REPLACE_EXISTING);
}
logger.info("源文件下载到临时路径: {}", tempInput.toAbsolutePath());
Path tempOutput = Files.createTempFile("converted_", "." + targetExtension);
try {
converter.convert(tempInput.toFile())
.to(tempOutput.toFile())
.execute();
logger.info("转换完成,临时输出: {}", tempOutput.toAbsolutePath());
byte[] resultBytes = Files.readAllBytes(tempOutput);
logger.info("转换结果大小: {} bytes", resultBytes.length);
return resultBytes;
} catch (OfficeException e) {
logger.error("转换失败 (格式: {})", targetExtension, e);
throw new Exception("文档转换失败 (格式: " + targetExtension + "): " + e.getMessage(), e);
} finally {
try {
Files.deleteIfExists(tempInput);
Files.deleteIfExists(tempOutput);
} catch (Exception ignored) {
logger.warn("清理临时文件失败");
}
}
}
@PreDestroy
public void destroy() {
OfficeManagerHolder.stop();
}
}
\ No newline at end of file
......@@ -291,5 +291,13 @@
<orderEntry type="library" name="Maven: org.apache.commons:commons-compress:1.19" level="project" />
<orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.06" level="project" />
<orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:3.1.0" level="project" />
<orderEntry type="library" name="Maven: org.jodconverter:jodconverter-core:4.4.7" level="project" />
<orderEntry type="library" name="Maven: org.jodconverter:jodconverter-local:4.4.7" level="project" />
<orderEntry type="library" name="Maven: org.openoffice:juh:4.1.2" level="project" />
<orderEntry type="library" name="Maven: org.openoffice:jurt:4.1.2" level="project" />
<orderEntry type="library" name="Maven: org.openoffice:ridl:4.1.2" level="project" />
<orderEntry type="library" name="Maven: org.openoffice:unoil:4.1.2" level="project" />
<orderEntry type="library" name="Maven: com.itextpdf:itextpdf:5.5.13" level="project" />
<orderEntry type="library" name="Maven: com.itextpdf:itext-asian:5.2.0" level="project" />
</component>
</module>
\ No newline at end of file
package com.yd.oss.feign.client;
import com.yd.common.result.Result;
import com.yd.oss.feign.fallback.ApiChunkedUploadContextFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
/**
* 分片上传上下文信息Feign客户端
*/
@FeignClient(name = "yd-oss-api", path = "/oss/api/chunkedUploadContext", fallbackFactory = ApiChunkedUploadContextFeignFallbackFactory.class)
public interface ApiChunkedUploadContextFeignClient {
/**
* 上传单个分片
* @param chunk
* @param taskId
* @param chunkIndex
* @param projectBizId
* @param source
* @return
*/
@PostMapping(value = "/uploadChunk", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
Result<Void> uploadChunk(
@RequestPart("chunk") MultipartFile chunk,
@RequestParam("taskId") String taskId,
@RequestParam("chunkIndex") Integer chunkIndex,
@RequestParam("projectBizId") String projectBizId,
@RequestParam("source") String source
);
/**
* 完成分片上传(合并)
*/
@PostMapping("/finishChunks")
Result<Map<String, Object>> finishChunks(
@RequestParam("taskId") String taskId,
@RequestParam("projectBizId") String projectBizId
);
}
......@@ -10,14 +10,14 @@ import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* OSS服务信息Feign客户端
*/
@FeignClient(name = "yd-oss-api", fallbackFactory = ApiOssFeignFallbackFactory.class)
@FeignClient(name = "yd-oss-api",
path = "/oss/api/oss",
fallbackFactory = ApiOssFeignFallbackFactory.class)
public interface ApiOssFeignClient {
/**
......@@ -42,7 +42,10 @@ public interface ApiOssFeignClient {
Result<ApiUploadResponse> uploadFileBody(@RequestPart("file") MultipartFile file,
@RequestPart("request") ApiUploadFileRequest request);
@PostMapping(value = "/upload/body/json", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
Result<ApiUploadResponse> uploadFileBodyWithJson(
@RequestPart("file") MultipartFile file,
@RequestPart("request") String requestJson);
/**
* 下载文件
......
package com.yd.oss.feign.fallback;
import com.yd.common.result.Result;
import com.yd.oss.feign.client.ApiChunkedUploadContextFeignClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
/**
* 分片上传上下文信息Feign降级处理
*/
@Slf4j
@Component
public class ApiChunkedUploadContextFeignFallbackFactory implements FallbackFactory<ApiChunkedUploadContextFeignClient> {
@Override
public ApiChunkedUploadContextFeignClient create(Throwable cause) {
return new ApiChunkedUploadContextFeignClient() {
@Override
public Result<Void> uploadChunk(MultipartFile chunk, String taskId, Integer chunkIndex, String projectBizId, String source) {
return null;
}
@Override
public Result<Map<String, Object>> finishChunks(String taskId, String projectBizId) {
return null;
}
};
}
}
......@@ -4,7 +4,6 @@ import com.yd.common.result.Result;
import com.yd.oss.feign.client.ApiExcelFeignClient;
import com.yd.oss.feign.dto.ExportResult;
import com.yd.oss.feign.request.ApiExportRequest;
import com.yd.oss.feign.request.ApiOssExcelParseRequest;
import com.yd.oss.feign.request.ApiOssExportAppointmentExcelRequest;
import com.yd.oss.feign.request.MultiSheetExportRequest;
import com.yd.oss.feign.response.ApiOssExcelParseResponse;
......
......@@ -33,6 +33,11 @@ public class ApiOssFeignFallbackFactory implements FallbackFactory<ApiOssFeignCl
}
@Override
public Result<ApiUploadResponse> uploadFileBodyWithJson(MultipartFile file, String requestJson) {
return null;
}
@Override
public Result downloadFile(String fileKey) {
return null;
}
......
......@@ -8,6 +8,11 @@ import javax.validation.constraints.NotBlank;
public class ApiUploadFileRequest {
/**
* 租户唯一标识(业务ID)
*/
private String tenantBizId;
/**
* 项目ID
*/
private String projectBizId;
......
......@@ -61,6 +61,6 @@ public class ApiUploadResponse {
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;
}
......@@ -120,5 +120,30 @@
<artifactId>xmlbeans</artifactId>
</dependency>
<!-- JodConverter 文档转换 -->
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-core</artifactId>
<version>4.4.7</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.4.7</version>
</dependency>
<!-- iText PDF 处理 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>
</project>
package com.yd.oss.service.dao;
import com.yd.oss.service.model.ChunkedUploadContext;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 分片上传上下文表(一个任务上传文件信息拆分成多个ETag上传存储,任务执行完毕,阿里云合并ETag列表为完整的文件信息) Mapper 接口
* </p>
*
* @author zxm
* @since 2026-08-05
*/
public interface ChunkedUploadContextMapper extends BaseMapper<ChunkedUploadContext> {
}
......@@ -15,6 +15,11 @@ import lombok.NoArgsConstructor;
public class OssUploadFileReqDto {
/**
* 租户唯一标识(业务ID)
*/
private String tenantBizId;
/**
* 项目ID
*/
private String projectBizId;
......
package com.yd.oss.service.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 分片上传上下文表(一个任务上传文件信息拆分成多个ETag上传存储,任务执行完毕,阿里云合并ETag列表为完整的文件信息)
* </p>
*
* @author zxm
* @since 2026-08-05
*/
@Getter
@Setter
@TableName("chunked_upload_context")
public class ChunkedUploadContext implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 任务ID
*/
@TableField("task_id")
private String taskId;
/**
* OSS 分片上传 ID(由 OSS 初始化时返回)
*/
@TableField("upload_id")
private String uploadId;
/**
* 文件在 OSS 中的完整路径(不含 Bucket 名称)
*/
@TableField("object_key")
private String objectKey;
/**
* 已上传分片的 ETag 列表(JSON 数组格式,如 [{"partNumber":1,"eTag":"xxx"}])
*/
@TableField("part_etags_json")
private String partEtagsJson;
/**
* 状态:0-初始化,1-上传中,2-已完成,3-已取消
*/
@TableField("status")
private Integer status;
/**
* 通用备注
*/
@TableField("remark")
private String remark;
/**
* 删除标识: 0-正常, 1-删除
*/
@TableField("is_deleted")
private Integer isDeleted;
/**
* 创建人ID
*/
@TableField("creator_id")
private String creatorId;
/**
* 更新人ID
*/
@TableField("updater_id")
private String updaterId;
/**
* 创建时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField("update_time")
private LocalDateTime updateTime;
}
package com.yd.oss.service.service;
import com.yd.oss.service.model.ChunkedUploadContext;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 分片上传上下文表(一个任务上传文件信息拆分成多个ETag上传存储,任务执行完毕,阿里云合并ETag列表为完整的文件信息) 服务类
* </p>
*
* @author zxm
* @since 2026-08-05
*/
public interface IChunkedUploadContextService extends IService<ChunkedUploadContext> {
}
package com.yd.oss.service.service.impl;
import com.alibaba.fastjson2.JSON;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.OSSObject;
......@@ -83,7 +84,7 @@ public class AliYunOssServiceImpl implements OssService {
OSS ossClient = null;
try {
ossClient = ossClientFactory.createOssClient(provider);
return doUploadFile(ossClient, provider, inputStream, fileName, bucketName, uploadUser, type, null, null, null, null, null, null);
return doUploadFile(ossClient, provider, inputStream, fileName, bucketName, uploadUser, type, null, null, null, null, null, null,null,null);
} finally {
if (ossClient != null) {
ossClient.shutdown();
......@@ -115,7 +116,8 @@ public class AliYunOssServiceImpl implements OssService {
FileUtil.getFileType(file.getOriginalFilename()),
reqDto.getObjectBizId(), reqDto.getObjectName(),
reqDto.getObjectTableName(), reqDto.getObjectType(),
reqDto.getObjectBizId(), reqDto.getObjectName()); // 这里需要根据实际情况调整,原代码中存储了object信息
reqDto.getObjectBizId(), reqDto.getObjectName(),
reqDto.getTenantBizId(),reqDto.getProjectBizId()); // 这里需要根据实际情况调整,原代码中存储了object信息
} catch (IOException e) {
log.error("文件输入流解析异常", e);
throw new BusinessException("文件输入流解析异常");
......@@ -142,7 +144,7 @@ public class AliYunOssServiceImpl implements OssService {
try {
ossClient = ossClientFactory.createOssClient(defaultProvider);
OssUploadFileResDto result = doUploadFile(ossClient, defaultProvider, inputStream, fileName,
defaultProvider.getBucketName(), uploadUser, null, null, null, null, null, null, null);
defaultProvider.getBucketName(), uploadUser, null, null, null, null, null, null, null,null,null);
return result.getUrl();
} finally {
if (ossClient != null) {
......@@ -159,7 +161,8 @@ public class AliYunOssServiceImpl implements OssService {
String bucketName, String uploadUser, String type,
String objectBizId, String objectName,
String objectTableName, String objectType,
String creatorId, String creatorName) {
String creatorId, String creatorName,
String tenantBizId,String projectBizId) {
LocalDateTime now = LocalDateTime.now();
long startTime = System.currentTimeMillis();
String operationResult = "success";
......@@ -203,8 +206,15 @@ public class AliYunOssServiceImpl implements OssService {
ossFile.setObjectName(objectName);
ossFile.setObjectTableName(objectTableName);
ossFile.setObjectType(objectType);
ossFile.setTenantBizId(tenantBizId);
ossFile.setProjectBizId(projectBizId);
// 获取当前登录用户信息(如果存在)
AuthUserDto authUserDto = SecurityUtil.getCurrentLoginUser();
AuthUserDto authUserDto = null;
try {
authUserDto = SecurityUtil.getCurrentLoginUser();
}catch (Exception e){
log.info("获取当前登录用户信息失败:{}", e.getMessage());
}
if (authUserDto != null) {
ossFile.setCreatorId(authUserDto.getUserBizId());
ossFile.setCreatorName(authUserDto.getRealName());
......
package com.yd.oss.service.service.impl;
import com.yd.oss.service.model.ChunkedUploadContext;
import com.yd.oss.service.dao.ChunkedUploadContextMapper;
import com.yd.oss.service.service.IChunkedUploadContextService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 分片上传上下文表(一个任务上传文件信息拆分成多个ETag上传存储,任务执行完毕,阿里云合并ETag列表为完整的文件信息) 服务实现类
* </p>
*
* @author zxm
* @since 2026-08-05
*/
@Service
public class ChunkedUploadContextServiceImpl extends ServiceImpl<ChunkedUploadContextMapper, ChunkedUploadContext> implements IChunkedUploadContextService {
}
......@@ -21,7 +21,7 @@ public class MyBatisPlusCodeGenerator {
})
.strategyConfig(builder -> {
builder.addInclude(
"material","rel_object_material"
"chunked_upload_context"
)
.entityBuilder()
.enableLombok()
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yd.oss.service.dao.ChunkedUploadContextMapper">
</mapper>
......@@ -287,5 +287,13 @@
<orderEntry type="library" name="Maven: org.apache.commons:commons-compress:1.19" level="project" />
<orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.06" level="project" />
<orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:3.1.0" level="project" />
<orderEntry type="library" name="Maven: org.jodconverter:jodconverter-core:4.4.7" level="project" />
<orderEntry type="library" name="Maven: org.jodconverter:jodconverter-local:4.4.7" level="project" />
<orderEntry type="library" name="Maven: org.openoffice:juh:4.1.2" level="project" />
<orderEntry type="library" name="Maven: org.openoffice:jurt:4.1.2" level="project" />
<orderEntry type="library" name="Maven: org.openoffice:ridl:4.1.2" level="project" />
<orderEntry type="library" name="Maven: org.openoffice:unoil:4.1.2" level="project" />
<orderEntry type="library" name="Maven: com.itextpdf:itextpdf:5.5.13" level="project" />
<orderEntry type="library" name="Maven: com.itextpdf:itext-asian:5.2.0" level="project" />
</component>
</module>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment