文件上传 优化
This commit is contained in:
parent
0b5017d0bb
commit
7a3701de92
|
|
@ -3,6 +3,7 @@ package com.bonus.web.service.common;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.bonus.common.constant.Constants;
|
import com.bonus.common.constant.Constants;
|
||||||
import com.bonus.common.core.domain.AjaxResult;
|
import com.bonus.common.core.domain.AjaxResult;
|
||||||
|
import com.bonus.common.domain.file.po.ResourceFileRecordPo;
|
||||||
import com.bonus.common.domain.ocr.dto.OcrRequest;
|
import com.bonus.common.domain.ocr.dto.OcrRequest;
|
||||||
import com.bonus.common.domain.ocr.vo.OcrResponse;
|
import com.bonus.common.domain.ocr.vo.OcrResponse;
|
||||||
import com.bonus.file.config.MinioConfig;
|
import com.bonus.file.config.MinioConfig;
|
||||||
|
|
@ -10,6 +11,7 @@ import com.bonus.file.enums.UploadSuffixEnum;
|
||||||
import com.bonus.file.service.FileUploadService;
|
import com.bonus.file.service.FileUploadService;
|
||||||
import com.bonus.common.utils.FileUtil;
|
import com.bonus.common.utils.FileUtil;
|
||||||
import com.bonus.file.util.MinioUtil;
|
import com.bonus.file.util.MinioUtil;
|
||||||
|
import com.bonus.framework.manager.AsyncManager;
|
||||||
import com.bonus.ocr.service.OcrService;
|
import com.bonus.ocr.service.OcrService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
@ -96,7 +98,9 @@ public class CommonUploadService {
|
||||||
if(StringUtils.isEmpty(uploadResult)){
|
if(StringUtils.isEmpty(uploadResult)){
|
||||||
return AjaxResult.error(Constants.UPLOAD_ERROR);
|
return AjaxResult.error(Constants.UPLOAD_ERROR);
|
||||||
}
|
}
|
||||||
map.put("fileRes", FileUtil.getFileInfo(file,uploadPath,jsonObj.getString("fileUploadType")));
|
Map<String, Object> fileUploadType = FileUtil.getFileInfo(file, uploadPath, jsonObj.getString("fileUploadType"));
|
||||||
|
map.put("fileRes", fileUploadType);
|
||||||
|
AsyncManager.me().executeSaveResourceFileModule(createVo(fileUploadType));
|
||||||
return AjaxResult.success(Constants.UPLOAD_SUCCESS,map);
|
return AjaxResult.success(Constants.UPLOAD_SUCCESS,map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,10 +169,24 @@ public class CommonUploadService {
|
||||||
log.error(e.toString(),e.getMessage());
|
log.error(e.toString(),e.getMessage());
|
||||||
return AjaxResult.error(Constants.UPLOAD_ERROR);
|
return AjaxResult.error(Constants.UPLOAD_ERROR);
|
||||||
}
|
}
|
||||||
|
Map<String, Object> fileUploadType = FileUtil.getFileInfo(file, uploadPath, jsonObj.getString("fileUploadType"));
|
||||||
map.put("fileRes", FileUtil.getFileInfo(file,uploadPath,jsonObj.getString("fileUploadType")));
|
map.put("fileRes", FileUtil.getFileInfo(file,uploadPath,jsonObj.getString("fileUploadType")));
|
||||||
map.put("ocrResult", ocrResponse);
|
map.put("ocrResult", ocrResponse);
|
||||||
|
AsyncManager.me().executeSaveResourceFileModule(createVo(fileUploadType));
|
||||||
return AjaxResult.success(Constants.UPLOAD_SUCCESS,map);
|
return AjaxResult.success(Constants.UPLOAD_SUCCESS,map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建资源文件实体
|
||||||
|
* @param map
|
||||||
|
* @return ResourceFileRecordPo
|
||||||
|
* @author cwchen
|
||||||
|
* @date 2025/11/14 15:44
|
||||||
|
*/
|
||||||
|
public ResourceFileRecordPo createVo(Map<String, Object> map){
|
||||||
|
ResourceFileRecordPo po = new ResourceFileRecordPo();
|
||||||
|
po.setFilePath(map.get("filePath").toString());
|
||||||
|
return po;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -204,13 +204,6 @@
|
||||||
<version>${io.jsonwebtoken.version}</version>
|
<version>${io.jsonwebtoken.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--onlyoffice集成的sdk-->
|
|
||||||
<!--<dependency>
|
|
||||||
<groupId>com.onlyoffice</groupId>
|
|
||||||
<artifactId>docs-integration-sdk</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
</dependency>-->
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.auth0</groupId>
|
<groupId>com.auth0</groupId>
|
||||||
<artifactId>java-jwt</artifactId>
|
<artifactId>java-jwt</artifactId>
|
||||||
|
|
@ -222,6 +215,13 @@
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.8.11</version>
|
<version>5.8.11</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 连接池 -->
|
||||||
|
<!--<dependency>
|
||||||
|
<groupId>com.rabbitmq</groupId>
|
||||||
|
<artifactId>amqp-client</artifactId>
|
||||||
|
<version>${amqp-client.version}</version>
|
||||||
|
</dependency>-->
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.bonus.common.domain.file.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className:ResourceFileRecordPo
|
||||||
|
* @author:cwchen
|
||||||
|
* @date:2025-11-14-15:23
|
||||||
|
* @version:1.0
|
||||||
|
* @description:系统资源存储记录-po
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ResourceFileRecordPo {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String filePath;
|
||||||
|
|
||||||
|
private Date createDate = new Date();
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.bonus.common.utils.ip;
|
package com.bonus.common.utils.ip;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.*;
|
||||||
import java.net.UnknownHostException;
|
import java.util.Enumeration;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import com.bonus.common.utils.ServletUtils;
|
import com.bonus.common.utils.ServletUtils;
|
||||||
import com.bonus.common.utils.StringUtils;
|
import com.bonus.common.utils.StringUtils;
|
||||||
|
|
@ -216,16 +216,84 @@ public class IpUtils
|
||||||
*
|
*
|
||||||
* @return 本地IP地址
|
* @return 本地IP地址
|
||||||
*/
|
*/
|
||||||
public static String getHostIp()
|
public static String getHostIp() {
|
||||||
{
|
return getHostIp(false);
|
||||||
try
|
}
|
||||||
{
|
|
||||||
|
public static String getHostIp(boolean preferPublic) {
|
||||||
|
// 先尝试获取本地IP
|
||||||
|
String ip = getLocalNetworkIp();
|
||||||
|
|
||||||
|
if (!"127.0.0.1".equals(ip)) {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果还是127.0.0.1,尝试其他方法
|
||||||
|
if (preferPublic) {
|
||||||
|
String publicIp = getPublicIpBySocket();
|
||||||
|
if (!"127.0.0.1".equals(publicIp)) {
|
||||||
|
return publicIp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getLocalNetworkIp() {
|
||||||
|
try {
|
||||||
|
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
||||||
|
while (interfaces.hasMoreElements()) {
|
||||||
|
NetworkInterface networkInterface = interfaces.nextElement();
|
||||||
|
|
||||||
|
// 过滤条件
|
||||||
|
if (networkInterface.isLoopback() ||
|
||||||
|
!networkInterface.isUp() ||
|
||||||
|
networkInterface.isVirtual() ||
|
||||||
|
networkInterface.isPointToPoint()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排除Docker、VMware等虚拟网卡
|
||||||
|
String displayName = networkInterface.getDisplayName().toLowerCase();
|
||||||
|
if (displayName.contains("docker") ||
|
||||||
|
displayName.contains("vmware") ||
|
||||||
|
displayName.contains("virtual")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
|
||||||
|
while (addresses.hasMoreElements()) {
|
||||||
|
InetAddress address = addresses.nextElement();
|
||||||
|
if (address instanceof Inet4Address && !address.isLoopbackAddress()) {
|
||||||
|
String ip = address.getHostAddress();
|
||||||
|
// 排除特殊网段
|
||||||
|
if (!ip.startsWith("169.254") &&
|
||||||
|
!ip.startsWith("127.") &&
|
||||||
|
!ip.startsWith("0.")) {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SocketException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最终回退
|
||||||
|
try {
|
||||||
return InetAddress.getLocalHost().getHostAddress();
|
return InetAddress.getLocalHost().getHostAddress();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
return "127.0.0.1";
|
||||||
}
|
}
|
||||||
catch (UnknownHostException e)
|
}
|
||||||
{
|
|
||||||
|
private static String getPublicIpBySocket() {
|
||||||
|
try (Socket socket = new Socket()) {
|
||||||
|
socket.connect(new InetSocketAddress("8.8.8.8", 53), 3000);
|
||||||
|
return socket.getLocalAddress().getHostAddress();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "127.0.0.1";
|
||||||
}
|
}
|
||||||
return "127.0.0.1";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.bonus.file.mapper;
|
package com.bonus.file.mapper;
|
||||||
|
|
||||||
import com.bonus.common.domain.file.po.ResourceFilePo;
|
import com.bonus.common.domain.file.po.ResourceFilePo;
|
||||||
|
import com.bonus.common.domain.file.po.ResourceFileRecordPo;
|
||||||
import com.bonus.common.domain.file.vo.ResourceFileVo;
|
import com.bonus.common.domain.file.vo.ResourceFileVo;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
@ -66,4 +67,22 @@ public interface ISourceFileMapper {
|
||||||
* @date 2025/10/24 11:10
|
* @date 2025/10/24 11:10
|
||||||
*/
|
*/
|
||||||
void delResourceFileBybusinessId(List<ResourceFilePo> delFiles);
|
void delResourceFileBybusinessId(List<ResourceFilePo> delFiles);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据文件id获取文件对象
|
||||||
|
* @param po
|
||||||
|
* @return ResourceFileVo
|
||||||
|
* @author cwchen
|
||||||
|
* @date 2025/11/7 22:15
|
||||||
|
*/
|
||||||
|
ResourceFileVo getFileById(ResourceFilePo po);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加系统资源存储记录
|
||||||
|
* @param list
|
||||||
|
* @return void
|
||||||
|
* @author cwchen
|
||||||
|
* @date 2025/11/14 15:26
|
||||||
|
*/
|
||||||
|
void addResourceFileRecord(List<ResourceFileRecordPo> list);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,299 +0,0 @@
|
||||||
/*
|
|
||||||
package com.bonus.file.service;
|
|
||||||
|
|
||||||
import com.bonus.common.core.domain.model.LoginUser;
|
|
||||||
import com.bonus.common.domain.file.vo.OnlyOfficeCallback;
|
|
||||||
import com.bonus.common.utils.FileUtil;
|
|
||||||
import com.bonus.common.utils.SecurityUtils;
|
|
||||||
import com.bonus.common.utils.ip.IpUtils;
|
|
||||||
import com.bonus.file.config.OnlyOfficeConfig;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @className:OnlyOfficeService
|
|
||||||
* @author:cwchen
|
|
||||||
* @date:2025-11-03-16:14
|
|
||||||
* @version:1.0
|
|
||||||
* @description:OnlyOffice 服务类
|
|
||||||
*//*
|
|
||||||
|
|
||||||
@Service(value = "OnlyOfficeService")
|
|
||||||
@Slf4j
|
|
||||||
@CrossOrigin(origins = "*")
|
|
||||||
public class OnlyOfficeService {
|
|
||||||
|
|
||||||
@Resource(name = "FileUploadService")
|
|
||||||
private FileUploadService fileUploadService;
|
|
||||||
|
|
||||||
@Resource(name = "OnlyOfficeJwtService")
|
|
||||||
private OnlyOfficeJwtService onlyOfficeJwtService;
|
|
||||||
|
|
||||||
@Resource(name = "OnlyOfficeConfig")
|
|
||||||
private OnlyOfficeConfig onlyOfficeConfig;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
|
||||||
|
|
||||||
private static final String DOCUMENT_CACHE_KEY = "document:";
|
|
||||||
|
|
||||||
public Map<String, Object> getConfigWithToken(String fileKey, String fileName, String type, String mode) throws Exception {
|
|
||||||
Map<String, Object> map = buildEditorConfig(fileKey, fileName, type, mode);
|
|
||||||
String token = generateJwtToken(map);
|
|
||||||
map.put("token", token);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> buildEditorConfig(String fileKey, String fileName, String type, String mode) throws Exception {
|
|
||||||
|
|
||||||
// 清理文件名,只保留最终文件名
|
|
||||||
String cleanFileName = extractFileName(fileName);
|
|
||||||
String fileUrl = fileUploadService.getFile(fileName).getFilePath();
|
|
||||||
Map<String, Object> config = new HashMap<>();
|
|
||||||
|
|
||||||
// 文档配置
|
|
||||||
Map<String, Object> document = new HashMap<>();
|
|
||||||
document.put("title", cleanFileName);
|
|
||||||
document.put("url", fileUrl);
|
|
||||||
document.put("fileType", getFileExtension(fileName));
|
|
||||||
document.put("key", fileKey);
|
|
||||||
document.put("permissions", buildPermissions(mode));
|
|
||||||
|
|
||||||
// 编辑器配置
|
|
||||||
Map<String, Object> editorConfig = new HashMap<>();
|
|
||||||
editorConfig.put("mode", mode);
|
|
||||||
editorConfig.put("lang", "zh-CN");
|
|
||||||
editorConfig.put("callbackUrl", buildCallbackUrl());
|
|
||||||
|
|
||||||
// 用户信息
|
|
||||||
Map<String, Object> user = new HashMap<>();
|
|
||||||
user.put("id", getCurrentUserId() + "");
|
|
||||||
user.put("name", getCurrentUserName());
|
|
||||||
|
|
||||||
editorConfig.put("user", user);
|
|
||||||
|
|
||||||
// 自定义配置
|
|
||||||
Map<String, Object> customization = new HashMap<>();
|
|
||||||
customization.put("forcesave", false);
|
|
||||||
customization.put("about", true);
|
|
||||||
customization.put("feedback", true);
|
|
||||||
customization.put("hideRightMenu", true);
|
|
||||||
customization.put("compactToolbar", true);
|
|
||||||
editorConfig.put("customization", customization);
|
|
||||||
|
|
||||||
config.put("document", document);
|
|
||||||
config.put("documentType", getDocumentType(fileName));
|
|
||||||
config.put("editorConfig", editorConfig);
|
|
||||||
config.put("type", type);
|
|
||||||
config.put("width", "100%");
|
|
||||||
config.put("height", "100%");
|
|
||||||
// 缓存文档信息
|
|
||||||
// cacheDocumentInfo(fileKey, fileName);
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleCallback(OnlyOfficeCallback callback, HttpServletResponse response) throws Exception {
|
|
||||||
PrintWriter writer = response.getWriter();
|
|
||||||
log.info("收到 OnlyOffice 回调, 状态: {}, Key: {}", callback.getStatus(), callback.getKey());
|
|
||||||
switch (callback.getStatus()) {
|
|
||||||
case OnlyOfficeCallback.STATUS_READY_FOR_SAVE:
|
|
||||||
case OnlyOfficeCallback.STATUS_FORCE_SAVE:
|
|
||||||
saveDocumentFromCallback(callback);
|
|
||||||
break;
|
|
||||||
case OnlyOfficeCallback.STATUS_DOCUMENT_EDITED:
|
|
||||||
log.info("文档已被编辑: {}", callback.getKey());
|
|
||||||
break;
|
|
||||||
case OnlyOfficeCallback.STATUS_CLOSED_NO_CHANGES:
|
|
||||||
log.info("文档关闭,无更改: {}", callback.getKey());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log.info("文档状态: {}", callback.getStatus());
|
|
||||||
}
|
|
||||||
writer.write("{\"error\":0}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveDocumentFromCallback(OnlyOfficeCallback callback) {
|
|
||||||
try {
|
|
||||||
String fileName = getCachedFileName(callback.getKey());
|
|
||||||
if (fileName == null) {
|
|
||||||
log.error("未找到缓存的文档信息: {}", callback.getKey());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从 OnlyOffice 下载最新版本
|
|
||||||
String downloadUrl = callback.getUrl();
|
|
||||||
byte[] fileContent = downloadFileFromUrl(downloadUrl);
|
|
||||||
|
|
||||||
// 保存到 MinIO
|
|
||||||
saveToMinio(fileName, fileContent);
|
|
||||||
|
|
||||||
log.info("文档保存成功: {}", fileName);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("保存文档失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] downloadFileFromUrl(String url) throws Exception {
|
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
|
||||||
ResponseEntity<byte[]> response = restTemplate.getForEntity(url, byte[].class);
|
|
||||||
return response.getBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveToMinio(String fileName, byte[] content) throws Exception {
|
|
||||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(content);
|
|
||||||
fileUploadService.uploadFile(FileUtil.createMultipartFile(fileName, fileName,
|
|
||||||
"application/octet-stream", inputStream), fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cacheDocumentInfo(String fileKey, String fileName) {
|
|
||||||
redisTemplate.opsForValue().set(DOCUMENT_CACHE_KEY + fileKey, fileName,
|
|
||||||
Duration.ofHours(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCachedFileName(String fileKey) {
|
|
||||||
return (String) redisTemplate.opsForValue().get(DOCUMENT_CACHE_KEY + fileKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildCallbackUrl() {
|
|
||||||
String hostIp = IpUtils.getHostIp();
|
|
||||||
// log.info("服务器ip:{}", hostIp);
|
|
||||||
return "http://" + hostIp + ":" + onlyOfficeConfig.getServerPort() + "/smartBid/documents/callback";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String getFileExtension(String fileName) {
|
|
||||||
return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, Boolean> buildPermissions(String mode) {
|
|
||||||
Map<String, Boolean> permissions = new HashMap<>();
|
|
||||||
boolean canEdit = "edit".equals(mode);
|
|
||||||
permissions.put("edit", canEdit);
|
|
||||||
permissions.put("download", true);
|
|
||||||
permissions.put("review", true);
|
|
||||||
permissions.put("print", true);
|
|
||||||
permissions.put("copy", true);
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getDocumentType(String fileName) {
|
|
||||||
String ext = getFileExtension(fileName);
|
|
||||||
switch (ext) {
|
|
||||||
case "docx":
|
|
||||||
case "doc":
|
|
||||||
case "odt":
|
|
||||||
case "rtf":
|
|
||||||
case "txt":
|
|
||||||
case "docm":
|
|
||||||
case "dot":
|
|
||||||
case "dotx":
|
|
||||||
case "dotm":
|
|
||||||
case "fodt":
|
|
||||||
case "ott":
|
|
||||||
case "html":
|
|
||||||
case "htm":
|
|
||||||
case "mht":
|
|
||||||
case "xml":
|
|
||||||
return "word"; // 修改: text → word
|
|
||||||
case "xlsx":
|
|
||||||
case "xls":
|
|
||||||
case "ods":
|
|
||||||
case "csv":
|
|
||||||
case "xlsm":
|
|
||||||
case "xlt":
|
|
||||||
case "xltx":
|
|
||||||
case "xltm":
|
|
||||||
case "fods":
|
|
||||||
case "ots":
|
|
||||||
return "cell"; // 修改: spreadsheet → cell
|
|
||||||
case "pptx":
|
|
||||||
case "ppt":
|
|
||||||
case "odp":
|
|
||||||
case "pptm":
|
|
||||||
case "pot":
|
|
||||||
case "potx":
|
|
||||||
case "potm":
|
|
||||||
case "fodp":
|
|
||||||
case "otp":
|
|
||||||
return "slide"; // 修改: presentation → slide
|
|
||||||
case "pdf":
|
|
||||||
return "pdf"; // 保持不变
|
|
||||||
case "vsdx":
|
|
||||||
case "vssx":
|
|
||||||
case "vsd":
|
|
||||||
case "vss":
|
|
||||||
return "diagram"; // 新增图表类型
|
|
||||||
default:
|
|
||||||
return "word"; // 修改: text → word
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Long getCurrentUserId() {
|
|
||||||
// 获取用户ID
|
|
||||||
return Optional.ofNullable(SecurityUtils.getLoginUser())
|
|
||||||
.map(LoginUser::getUserId)
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCurrentUserName() {
|
|
||||||
// 获取用户名
|
|
||||||
return Optional.ofNullable(SecurityUtils.getLoginUser())
|
|
||||||
.map(LoginUser::getUsername)
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提取文件名(去掉路径)
|
|
||||||
private String extractFileName(String filePath) {
|
|
||||||
if (filePath == null) return "document";
|
|
||||||
int lastSlash = filePath.lastIndexOf("/");
|
|
||||||
int lastBackslash = filePath.lastIndexOf("\\");
|
|
||||||
int lastIndex = Math.max(lastSlash, lastBackslash);
|
|
||||||
return lastIndex >= 0 ? filePath.substring(lastIndex + 1) : filePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* 生成 JWT Token(OnlyOffice 专用格式)
|
|
||||||
*//*
|
|
||||||
|
|
||||||
private String generateJwtToken(Map<String, Object> config) {
|
|
||||||
try {
|
|
||||||
// OnlyOffice 需要的 payload 结构
|
|
||||||
Map<String, Object> payload = new HashMap<>();
|
|
||||||
// 复制整个配置到 payload
|
|
||||||
payload.put("document", config.get("document"));
|
|
||||||
payload.put("editorConfig", config.get("editorConfig"));
|
|
||||||
payload.put("documentType", config.get("documentType"));
|
|
||||||
payload.put("type", config.get("type"));
|
|
||||||
payload.put("width", config.get("width"));
|
|
||||||
payload.put("height", config.get("height"));
|
|
||||||
|
|
||||||
// 使用 JWTUtil 生成 token
|
|
||||||
String token = onlyOfficeJwtService.generateToken(payload);
|
|
||||||
if (token == null) {
|
|
||||||
log.error("生成JWT Token失败");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
log.debug("生成的JWT Token: {}", token);
|
|
||||||
return token;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("生成JWT Token异常", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
package com.bonus.file.service;
|
package com.bonus.file.service;
|
||||||
|
|
||||||
import com.bonus.common.domain.file.po.ResourceFilePo;
|
import com.bonus.common.domain.file.po.ResourceFilePo;
|
||||||
|
import com.bonus.common.domain.file.po.ResourceFileRecordPo;
|
||||||
import com.bonus.common.domain.file.vo.ResourceFileVo;
|
import com.bonus.common.domain.file.vo.ResourceFileVo;
|
||||||
import com.bonus.common.domain.mainDatabase.dto.EnterpriseDto;
|
import com.bonus.common.domain.mainDatabase.dto.EnterpriseDto;
|
||||||
import com.bonus.file.mapper.ISourceFileMapper;
|
import com.bonus.file.mapper.ISourceFileMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
@ -101,4 +104,21 @@ public class SourceFileService {
|
||||||
public ResourceFileVo getFileById(ResourceFilePo po) {
|
public ResourceFileVo getFileById(ResourceFilePo po) {
|
||||||
return mapper.getFileById(po);
|
return mapper.getFileById(po);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加系统资源存储记录
|
||||||
|
* @param list
|
||||||
|
* @return void
|
||||||
|
* @author cwchen
|
||||||
|
* @date 2025/11/14 15:26
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void addResourceFileRecord(List<ResourceFileRecordPo> list){
|
||||||
|
try {
|
||||||
|
mapper.addResourceFileRecord(list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.toString(),e);
|
||||||
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,4 +93,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
FROM sys_resource_file
|
FROM sys_resource_file
|
||||||
WHERE source_id = #{sourceId} AND del_flag = '0'
|
WHERE source_id = #{sourceId} AND del_flag = '0'
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!--添加系统资源存储记录-->
|
||||||
|
<insert id="addResourceFileRecord">
|
||||||
|
INSERT INTO sys_resource_file_record
|
||||||
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
file_path,
|
||||||
|
create_date,
|
||||||
|
</trim>
|
||||||
|
VALUES
|
||||||
|
<foreach collection="list" item="item" separator=",">
|
||||||
|
(
|
||||||
|
#{item.filePath},
|
||||||
|
#{item.createDate}
|
||||||
|
)
|
||||||
|
</foreach>
|
||||||
|
</insert>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,10 @@
|
||||||
<groupId>com.bonus</groupId>
|
<groupId>com.bonus</groupId>
|
||||||
<artifactId>bonus-mainDatabase</artifactId>
|
<artifactId>bonus-mainDatabase</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.bonus</groupId>
|
||||||
|
<artifactId>bonus-file</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
package com.bonus.framework.manager;
|
package com.bonus.framework.manager;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
import com.bonus.common.domain.file.po.ResourceFileRecordPo;
|
||||||
import com.bonus.common.utils.Threads;
|
import com.bonus.common.utils.Threads;
|
||||||
import com.bonus.common.utils.spring.SpringUtils;
|
import com.bonus.common.utils.spring.SpringUtils;
|
||||||
|
import com.bonus.file.service.SourceFileService;
|
||||||
import com.bonus.system.domain.SysLogsVo;
|
import com.bonus.system.domain.SysLogsVo;
|
||||||
import com.bonus.system.service.ISysOperLogService;
|
import com.bonus.system.service.ISysOperLogService;
|
||||||
|
|
||||||
|
|
@ -90,6 +94,25 @@ public class AsyncManager
|
||||||
return execute(callable);
|
return execute(callable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行保存系统资源文件的异步任务
|
||||||
|
* @param resourceFileRecordPo
|
||||||
|
* @return Future<Map<String,String>>
|
||||||
|
* @author cwchen
|
||||||
|
* @date 2025/11/14 15:35
|
||||||
|
*/
|
||||||
|
public Future<Void> executeSaveResourceFileModule(final ResourceFileRecordPo resourceFileRecordPo) {
|
||||||
|
Callable<Void> callable = new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
List<ResourceFileRecordPo> list = Collections.singletonList(resourceFileRecordPo);
|
||||||
|
SpringUtils.getBean(SourceFileService.class).addResourceFileRecord(list);
|
||||||
|
return null; // 必须返回 null
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return execute(callable);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止任务线程池
|
* 停止任务线程池
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import com.bonus.common.constant.HttpStatus;
|
||||||
import com.bonus.common.core.domain.AjaxResult;
|
import com.bonus.common.core.domain.AjaxResult;
|
||||||
import com.bonus.common.utils.ServletUtils;
|
import com.bonus.common.utils.ServletUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
@ -33,10 +34,18 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
|
||||||
@Autowired
|
@Autowired
|
||||||
private TokenService tokenService;
|
private TokenService tokenService;
|
||||||
|
|
||||||
|
// onlyoffice忽略的回调函数访问路径
|
||||||
|
@Value("${ignoreUrl.callBackUrl}")
|
||||||
|
private String callBackUrl;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||||
throws ServletException, IOException
|
throws ServletException, IOException
|
||||||
{
|
{
|
||||||
|
if(request.getRequestURI().contains(callBackUrl)){
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
LoginUser loginUser = tokenService.getLoginUser(request);
|
LoginUser loginUser = tokenService.getLoginUser(request);
|
||||||
// 若检测到被其他设备挤下线,直接返回特定提示
|
// 若检测到被其他设备挤下线,直接返回特定提示
|
||||||
Object forced = request.getAttribute("forceLogoutByOtherDevice");
|
Object forced = request.getAttribute("forceLogoutByOtherDevice");
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ public class OcrService {
|
||||||
|
|
||||||
log.info("OCR服务开始识别");
|
log.info("OCR服务开始识别");
|
||||||
// 执行请求
|
// 执行请求
|
||||||
/*try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
|
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
|
||||||
HttpEntity entity = response.getEntity();
|
HttpEntity entity = response.getEntity();
|
||||||
String responseBody = EntityUtils.toString(entity, "UTF-8");
|
String responseBody = EntityUtils.toString(entity, "UTF-8");
|
||||||
log.info("OCR服务响应状态: {}", response.getStatusLine().getStatusCode());
|
log.info("OCR服务响应状态: {}", response.getStatusLine().getStatusCode());
|
||||||
|
|
@ -112,8 +112,8 @@ public class OcrService {
|
||||||
}
|
}
|
||||||
|
|
||||||
return ocrResponse;
|
return ocrResponse;
|
||||||
}*/
|
}
|
||||||
return null;
|
// return null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("调用OCR服务失败", e);
|
log.error("调用OCR服务失败", e);
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
1
pom.xml
1
pom.xml
|
|
@ -41,6 +41,7 @@
|
||||||
<minio.version>8.2.2</minio.version>
|
<minio.version>8.2.2</minio.version>
|
||||||
<commons-fileupload.version>1.4</commons-fileupload.version>
|
<commons-fileupload.version>1.4</commons-fileupload.version>
|
||||||
<io.jsonwebtoken.version>0.9.1</io.jsonwebtoken.version>
|
<io.jsonwebtoken.version>0.9.1</io.jsonwebtoken.version>
|
||||||
|
<amqp-client.version>5.16.0</amqp-client.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<!-- 依赖声明 -->
|
<!-- 依赖声明 -->
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue