weidy
2023-06-13 b5336d957680a1deb65d0565eed9c9eca630a738
文件服务的初步代码
已修改4个文件
已添加17个文件
2000 ■■■■■ 文件已修改
Source/UBCS/ubcs-ops-api/ubcs-resource-api/pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/bo/FileObjectBO.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/constant/FileBusConstant.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/constant/FileLifeConstant.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/dto/FileObjectDTO.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/dto/FileReleaseDTO.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/dto/FileShareDTO.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/entity/FileObject.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/life/FileLife.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/query/FileQuery.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/utils/FileDownloadUtil.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/utils/FileUtil.java 388 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/utils/ZipUtil.java 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/vo/FileObjectVO.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/controller/AttachController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/controller/FileController.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/endpoint/OssEndpoint.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/mapper/FileObjectMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/service/IFileService.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/service/impl/FileServiceImpl.java 536 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service-api/ubcs-util-api/src/main/java/com/vci/ubcs/starter/web/enumpck/BaseEnum.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops-api/ubcs-resource-api/pom.xml
@@ -23,6 +23,12 @@
            <groupId>org.springblade</groupId>
            <artifactId>blade-starter-tenant</artifactId>
        </dependency>
        <dependency>
            <groupId>com.vci.ubcs</groupId>
            <artifactId>ubcs-util-api</artifactId>
            <version>3.0.1.RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</project>
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/bo/FileObjectBO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.vci.ubcs.resource.bo;
import com.vci.ubcs.resource.vo.FileObjectVO;
import lombok.Data;
import java.io.InputStream;
/**
 * æ–‡ä»¶çš„业务对象
 * @author weidy
 * @date 2023/6/9
 */
@Data
public class FileObjectBO extends FileObjectVO {
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = -4887973911424096779L;
    /**
     * æ–‡ä»¶çš„æµ
     */
    private InputStream inputStream;
    /**
     * æ–‡ä»¶æœ¬åœ°çš„信息
     */
    private String fileLocalPath;
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/constant/FileBusConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.vci.ubcs.resource.constant;
/**
 * æ–‡ä»¶æœåŠ¡éƒ¨åˆ†çš„é™æ€å€¼
 * @author weidy
 * @date 2023/6/9
 */
public class FileBusConstant {
    /**
     * æ–‡ä»¶å¯¹è±¡
     */
    public static final String FILE_OBJECT = "fileObject";
    /**
     * æ–‡ä»¶ä¸‹è½½è®°å½•
     */
    public static final String FILE_DOWNLOAD_RECORD = "fileDownloadRecord";
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/constant/FileLifeConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
package com.vci.ubcs.resource.constant;
/**
 * æ–‡ä»¶çŠ¶æ€
 * @author weidy
 * @date 2023/6/9 9:07
 */
public class FileLifeConstant {
    /**
     * æ–‡ä»¶çš„状态
     */
    public static final String FILE = "fileStatus";
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/dto/FileObjectDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,54 @@
package com.vci.ubcs.resource.dto;
import com.vci.ubcs.resource.entity.FileObject;
import com.vci.ubcs.starter.web.pagemodel.BaseModelVO;
import lombok.Data;
/**
 * æ–‡ä»¶æ•°æ®ä¼ è¾“对象
 * @author weidy
 * @date 2023/6/9
 */
@Data
public class FileObjectDTO extends FileObject {
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = 497836915363113260L;
    /**
     * æ˜¯å¦ä¿®æ”¹æ–‡ä»¶
     */
    private Boolean updateFileFlag ;
    /**
     * æ–‡ä»¶å¤¹è·¯å¾„
     */
    private String dirPath;
    /**
     * æ–‡ä»¶ä¸Šä¼ åŽæ˜¯å¦ç«‹å³ç”Ÿæ•ˆ
     */
    private Boolean effect = true;
    /**
     * ä¸Šä¼ åŽŸæ–‡ä»¶è·¯å¾„
     */
    private String sourceFilePath;
    /**
     * æ ¡éªŒç›¸åŒçš„名称的文件,必须在ownbiz有值的情况下
     */
    private Boolean checkSameFile = false;
    /**
     * æ¡¶çš„名称
     */
    private String bucketName;
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/dto/FileReleaseDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package com.vci.ubcs.resource.dto;
import lombok.Data;
import java.util.List;
/**
 * æ–‡ä»¶å‘布的数据操作对象
 * @author weidy
 * @date 2023/6/9
 */
@Data
public class FileReleaseDTO implements java.io.Serializable{
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = -218379391237684940L;
    /**
     * æ‰€å±žæ•°æ®ä¸»é”®
     */
    private String ownbizOid;
    /**
     * æ‰€å±žæ•°æ®çš„业务类型
     */
    private String ownBtmName;
    /**
     * æ–‡ä»¶çš„主键
     */
    private List<String> oids;
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/dto/FileShareDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.vci.ubcs.resource.dto;
import lombok.Data;
import java.util.List;
/**
 * æ–‡ä»¶åˆ†äº«çš„æ•°æ®ä¼ è¾“对象
 * @author weidy
 * @date 2023/6/9
 */
@Data
public class FileShareDTO implements java.io.Serializable{
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = -2947163604655993790L;
    /**
     * æ¥æºä¸šåŠ¡
     */
    private String sourceBus;
    /**
     * æ¥æºä¸šåŠ¡æ•°æ®ä¸»é”®
     */
    private String sourceBusOid;
    /**
     * ç›®æ ‡çš„业务
     */
    private String targetBus;
    /**
     * ç›®æ ‡çš„业务数据主键
     */
    private String targetBusOid;
    /**
     * æºæ–‡ä»¶çš„主键
     */
    private List<String> oids;
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/entity/FileObject.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,90 @@
package com.vci.ubcs.resource.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.vci.ubcs.starter.revision.model.BaseModel;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * æ–‡ä»¶å¯¹è±¡
 * @author weidy
 * @date 2023/6/8
 */
@Data
@TableName("PL_SYS_FILEOBJECT")
@ApiModel(value = "文件对象", description = "存储业务数据关联的文件信息")
@EqualsAndHashCode(callSuper = true)
public class FileObject extends BaseModel {
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = -7116754635114431150L;
    /**
     * æ˜¾ç¤ºçš„名称
     */
    private String id;
    /**
     * æ–‡ä»¶åç§°
     */
    private String name;
    /**
     * åœ¨minio里的名称
     */
    private String objectName;
    /**
     * æ–‡ä»¶åŽç¼€å
     */
    private String fileExtension;
    /**
     * æ–‡æ¡£ç±»åž‹ç¼–号
     */
    private String fileDocClassify;
    /**
     * æ–‡æ¡£ç±»åž‹æ–‡æœ¬
     */
    private String fileDocClassifyName;
    /**
     * æ–‡ä»¶å¤§å°
     */
    private Long fileSize;
    /**
     * å…³é”®è¯ä¿¡æ¯
     */
    private String keyInfos;
    /**
     * æ‰€å±žæ•°æ®ä¸»é”®
     */
    private String ownbizOid;
    /**
     * æ‰€å±žæ•°æ®çš„业务类型
     */
    private String ownBtmName;
    /**
     * å…³è”的数据的信息
     */
    private String linkInfos;
    /**
     * æ–‡ä»¶çš„存储路径
     */
    private String fileLink;
    /**
     * æ¡¶çš„名称
     */
    private String bucketName;
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/life/FileLife.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
package com.vci.ubcs.resource.life;
import com.vci.ubcs.starter.web.enumpck.BaseEnum;
/**
 * æ–‡ä»¶çš„状态集合
 * @author weidy
 * @date 2023/6/11
 */
public enum FileLife implements BaseEnum {
    /**
     * åˆå§‹åŒ–
     */
    INIT("fileInit","初始化"),
    /**
     * ä¸Šä¼ ä¸­
     */
    TRANSITING("fileTransiting","上传中"),
    /**
     * ä¸Šä¼ å®Œæˆ
     */
    TRANS_FINISH("fileTransitFinish","上传完成"),
    /**
     * å·²ç”Ÿæ•ˆ
     */
    FILE_RELEASE("fileRelease","已生效");
    /**
     * æžšä¸¾å€¼
     */
    private String value;
    /**
     * æžšä¸¾æ˜¾ç¤ºå€¼
     */
    private String text;
    /**
     * èŽ·å–æžšä¸¾å€¼
     * @return æžšä¸¾å€¼
     */
    @Override
    public String getValue() {
        return value;
    }
    /**
     * è®¾ç½®æžšä¸¾å€¼
     * @param value æžšä¸¾å€¼
     */
    public void setValue(String value) {
        this.value = value;
    }
    /**
     * èŽ·å–æ˜¾ç¤ºæ–‡æœ¬
     * @return æ˜¾ç¤ºæ–‡æœ¬
     */
    @Override
    public String getText() {
        return text;
    }
    /**
     * è®¾ç½®æ˜¾ç¤ºæ–‡æœ¬
     * @param text æ˜¾ç¤ºæ–‡æœ¬
     */
    public void setText(String text) {
        this.text = text;
    }
    /**
     * æžšä¸¾å†…部构造方法
     * @param value æžšä¸¾å€¼
     * @param text æ˜¾ç¤ºæ–‡æœ¬
     */
    private FileLife(String value, String text){
        this.value = value;
        this.text = text;
    }
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/query/FileQuery.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
package com.vci.ubcs.resource.query;
import com.vci.ubcs.resource.entity.FileObject;
import com.vci.ubcs.starter.web.pagemodel.BladeQueryObject;
import lombok.Data;
import java.util.Date;
/**
 * æ–‡ä»¶çš„æŸ¥è¯¢
 * @author weidy
 * @date 2023/1/31
 */
@Data
public class FileQuery extends FileObject {
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = 2442917107957942183L;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    private Date createTime_begin;
    /**
     * åˆ›å»ºæ—¶é—´ç»“束
     */
    private Date createTime_end;
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/utils/FileDownloadUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,80 @@
package com.vci.ubcs.resource.utils;
import com.vci.ubcs.resource.bo.FileObjectBO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
/**
 * ä¸‹è½½æ–‡ä»¶çš„工具
 * @author weidy
 * @date 2023/6/9
 */
@Slf4j
public class FileDownloadUtil {
    /**
     * ä¸‹è½½æ–‡ä»¶
     * @param response å“åº”对象
     * @param fileObjectBO æ–‡ä»¶çš„信息,包含文件的输入流
     * @throws IOException ä¸‹è½½å¼‚常会抛出
     */
    public static void downloadFile(HttpServletResponse response, FileObjectBO fileObjectBO) throws IOException {
        downloadFile(response,fileObjectBO,true);
    }
    /**
     * ä¸‹è½½æ–‡ä»¶
     * @param response å“åº”对象
     * @param fileObjectBO æ–‡ä»¶çš„信息,包含文件的输入流
     * @param closeInputStream æ˜¯å¦å…³é—­æµ
     * @throws IOException ä¸‹è½½å‡ºé”™çš„æ—¶å€™æŠ›å‡ºå¼‚常
     */
    public static void downloadFile(HttpServletResponse response, FileObjectBO fileObjectBO,boolean closeInputStream) throws IOException {
        MediaType mediaType = MediaTypeFactory.getMediaType(fileObjectBO.getName() + "." + fileObjectBO.getFileExtension()).orElse(MediaType.APPLICATION_OCTET_STREAM);
        // è®¾ç½®å¼ºåˆ¶ä¸‹è½½ä¸æ‰“å¼€
        response.setContentType(mediaType.getType());
        try{
            String fileName = URLEncoder.encode(fileObjectBO.getName() + "." + fileObjectBO.getFileExtension(), "UTF8");
            response.addHeader("Content-Disposition", "attachment; filename="+ fileName+ ";filename*=utf-8''" + fileName);
        }catch(Exception e){
            if(log.isErrorEnabled()){
                log.error("设置文件的名称到响应流的时候出错",e);
            }
        }
        response.setCharacterEncoding("UTF-8");
        Cookie cookie = new Cookie("fileDownload", "true");
        cookie.setPath("/");
        response.addCookie(cookie);
        if(closeInputStream) {
            try (InputStream ins = (fileObjectBO.getInputStream() != null ? fileObjectBO.getInputStream() : new FileInputStream(fileObjectBO.getFileLocalPath()))) {
                IOUtils.copy(ins, response.getOutputStream());
            } catch (IOException e) {
                //有可能客户端的链接
                if (log.isErrorEnabled()) {
                    log.error("写入文件到响应流出错", e);
                }
                throw e;
            }
        }else{
            try {
                InputStream ins = (fileObjectBO.getInputStream() != null ? fileObjectBO.getInputStream() : new FileInputStream(fileObjectBO.getFileLocalPath()));
                IOUtils.copy(ins, response.getOutputStream());
            } catch (IOException e) {
                //有可能客户端的链接
                if (log.isErrorEnabled()) {
                    log.error("写入文件到响应流出错", e);
                }
                throw e;
            }
        }
    }
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/utils/FileUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,388 @@
package com.vci.ubcs.resource.utils;
import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.util.StringUtils;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
 * æœ¬åœ°æ–‡ä»¶æ“ä½œç±»
 * @author weidy
 * @date 2021-04-19
 */
public class FileUtil {
    /**
     * åˆ é™¤æ–‡ä»¶å¤¹
     * @param file è¦åˆ é™¤çš„æ–‡ä»¶æˆ–者文件夹
     */
    public static void deleteFile(File file) {
        if(file == null || !file.exists()){
            return;
        }
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                deleteFile(files[i]);
            }
        }
        file.delete();
    }
    /**
     * æ‹·è´æ–‡ä»¶
     * @param source æºæ–‡ä»¶
     * @param target ç›®æ ‡æ–‡ä»¶
     * @throws VciBaseException æ‹·è´æ–‡ä»¶å‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static void copyFile(File source, File target) throws VciBaseException {
        try(FileInputStream is = new FileInputStream(source);
            FileOutputStream os = new FileOutputStream(target)){
            FileChannel sourceChannel = is.getChannel();
            FileChannel targetChannel = os.getChannel();
            int i=0;
            int length=2097152;
            while(true){
                if(sourceChannel.position()==sourceChannel.size()){
                    sourceChannel.close();
                    targetChannel.close();
                    break;
                }
                if((sourceChannel.size()-sourceChannel.position())<20971520) {
                    length = (int) (sourceChannel.size() - sourceChannel.position());
                }else {
                    length = 20971520;
                }
                sourceChannel.transferTo(sourceChannel.position(),length,targetChannel);
                sourceChannel.position(sourceChannel.position()+length);
                i++;
            }
        }catch(Throwable e){
            throw new VciBaseException("拷贝文件出错",new String[0],e);
        }
    }
    /**
     * ä¸´æ—¶æ–‡ä»¶å¤¹çš„前缀
     */
    public static String DEFAULT_TEMP_FOLDER_PREFIX = "";
    /**
     * èŽ·å–é»˜è®¤çš„ä¸´æ—¶æ–‡ä»¶å¤¹
     * @return ä¸´æ—¶æ–‡ä»¶å¤¹ï¼Œé»˜è®¤ä¸ºå½“前项目的运行路径下的tempFolder下的随机值
     */
    public static String getDefaultTempFolder() throws VciBaseException{
        String path = (!StringUtils.hasLength(DEFAULT_TEMP_FOLDER_PREFIX)?getProjectFolder():DEFAULT_TEMP_FOLDER_PREFIX) + File.separator + "temp" + File.separator + VciBaseUtil.getPk();
        File folder = new File(path);
        if(!folder.exists()){
            folder.mkdirs();
        }
        return path;
    }
    /**
     * èŽ·å–é¡¹ç›®çš„è·¯å¾„
     * @return é¡¹ç›®çš„路径
     * @throws VciBaseException èŽ·å–è·¯å¾„å‡ºçŽ°äº†é”™è¯¯ä¼šæŠ›å‡ºå¼‚å¸¸
     */
    public static String getProjectFolder() throws VciBaseException{
        return getProjectFolder(FileUtil.class);
    }
    /**
     * èŽ·å–æŸä¸ªclass所在项目的路径
     * @param classObj æŸä¸ªclass
     * @return é¡¹ç›®çš„路径
     * @throws VciBaseException èŽ·å–è·¯å¾„å‡ºçŽ°äº†é”™è¯¯ä¼šæŠ›å‡ºå¼‚å¸¸
     */
    public static String getProjectFolder(Class classObj) throws VciBaseException{
        String path = "";
        try {
            ApplicationHome h = new ApplicationHome(classObj == null? FileUtil.class:classObj);
            File jarF = h.getSource();
            if(jarF == null){
                jarF = h.getDir();
            }
            path =  jarF.getParentFile().toString();
            if(path.contains("!")){
                path = new File(path).getParentFile().getParent();
            }
        }catch (Throwable e){
            throw new VciBaseException("获取当前服务所在的文件夹出现了错误",new String[0],e);
        }
        if(path.startsWith("file:\\")){
            path = path.substring(6);
        }
        if (System.getProperty("os.name").toLowerCase().startsWith("win") && path.startsWith("/")) {
            path = path.substring(path.indexOf("/") + 1);
        }
        return path;
    }
    /**
     * åˆ é™¤ä¸´æ—¶æ–‡ä»¶
     * @param tempFile ä¸´æ—¶æ–‡ä»¶
     * @param deleteRandomFolder æ˜¯å¦åˆ é™¤éšæœºçš„那个文件夹
     * @throws VciBaseException åˆ é™¤å‡ºé”™çš„æ—¶å€™æŠ›å‡ºå¼‚常
     */
    public static void deleteTempFile(File tempFile,boolean deleteRandomFolder) throws VciBaseException{
        if(tempFile!=null){
            tempFile.delete();
            if(deleteRandomFolder){
                tempFile.getParentFile().delete();
            }
        }
    }
    /**
     * åˆ¤æ–­å‚数是否为空
     * @param s å‚数,第一个为参数,第二个为提示信息
     * @throws VciBaseException ä¸ºç©ºæ—¶æŠ›å‡ºè¿™ä¸ªå¼‚常
     */
    public static void alertNotNull(Object... s) throws VciBaseException{
        if(s!=null && s.length>0){
            for(int i = 0 ; i < s.length ; i ++){
                Object obj = s[i];
                if(obj==null ||!StringUtils.hasLength(obj.toString())){
                    String param = "";
                    try{
                        i++;
                        param = s[i].toString();
                    }catch(Exception e){
                    }
                    throw new VciBaseException("参数[" + param + "]不能为空");
                }
            }
        }
    }
    /**
     * èŽ·å–æ–‡ä»¶çš„åŽç¼€å
     * @param file æ–‡ä»¶å¯¹è±¡
     * @return åŽç¼€åï¼Œä¸åŒ…含.;如果文件不存在或者没有后缀名返回""
     */
    public static String getFileExtension(File file){
        if(file!=null){
            return getFileExtensionByName(file.getName());
        }
        return "";
    }
    /**
     * èŽ·å–æ–‡ä»¶ä¸å«åŽç¼€åçš„åç§°
     * @param file æ–‡ä»¶
     * @return åç§°
     */
    public static String getFileNameUnHasExtension(File file){
        if(file!=null){
            String name = file.getName();
            return name.contains(".")?name.substring(0,name.lastIndexOf(".")):name;
        }
        return "";
    }
    /**
     * èŽ·å–æ–‡ä»¶ä¸å«åŽç¼€åçš„åç§°
     * @param fileName æ–‡ä»¶åç§°
     * @return åç§°
     */
    public static String getFileNameUnHasExtensionByName(String fileName){
        if(fileName!=null){
            return fileName.contains(".")?fileName.substring(0,fileName.lastIndexOf(".")):fileName;
        }
        return "";
    }
    /**
     * èŽ·å–æ–‡ä»¶çš„åŽç¼€å
     * @param name æ–‡ä»¶åç§°
     * @return åŽç¼€åï¼Œä¸åŒ…含.;没有后缀名返回""
     */
    public static String getFileExtensionByName(String name){
        if(StringUtils.hasLength(name)){
            if(name.contains(".")){
                return name.substring(name.lastIndexOf(".")+1);
            }
        }
        return "";
    }
    /**
     * èŽ·å–ä¸Šä¼ æ–‡ä»¶çš„åç§°ï¼Œåœ¨IE浏览器上,上传会把全路径带过来
     * @param name æ–‡ä»¶çš„名称
     * @return æ›¿æ¢åŽçš„值
     */
    public static String getFileNameForIE(String name){
        if(!StringUtils.hasLength(name)){
            return name;
        }
        if(name.contains(File.separator)){
            return name.substring(name.lastIndexOf(File.separator)+1);
        }
        if(name.contains("\\")){
            return name.substring(name.lastIndexOf("\\") + 1);
        }
        return name;
    }
    /**
     * ä»Žå·¥ç¨‹ä¸­è¯»å–文件的内容
     * @param fileName æ–‡ä»¶çš„名称
     * @return æ–‡ä»¶çš„内容
     * @throws VciBaseException è¯»å–出错的时候会抛出异常
     */
    public static String readContentForFileInJar(String fileName) throws VciBaseException{
        if(!StringUtils.hasLength(fileName)){
            throw new VciBaseException("文件名为空");
        }
        if(!fileName.startsWith("/")){
            fileName = "/" + fileName;
        }
        InputStream in = null;
        ByteArrayOutputStream os = null;
        try{
            in = FileUtil.class.getResourceAsStream( fileName);
            if(in ==null){
                in=Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
            }
            os = new ByteArrayOutputStream();
            IOUtils.copy(in,os);
            return new String(os.toByteArray(),"UTF-8");
        }catch (Throwable e){
            throw new VciBaseException("读取文件的内容出现了错误",new String[0],e);
        }finally {
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * è¯»å–文件的内容,文件不能是jar里的
     * @param fileName æ–‡ä»¶çš„名称
     * @return æ–‡ä»¶çš„内容,是UTF-8的字符集
     * @throws VciBaseException æ–‡ä»¶ä¸å­˜åœ¨ï¼Œå’Œè¯»å–出错的时候会抛出异常
     */
    public static String readContentForFile(String fileName) throws VciBaseException{
        return new String(readDataForFile(fileName),StandardCharsets.UTF_8);
    }
    /**
     * è¯»å–文件里的数据
     * @param fileName æ–‡ä»¶åç§°
     * @return æ–‡ä»¶çš„æ•°æ®
     * @throws VciBaseException æ–‡ä»¶ä¸å­˜åœ¨ï¼Œå’ŒèŽ·å–å‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚å¸¸
     */
    public static byte[] readDataForFile(String fileName) throws VciBaseException{
        File file = new File(fileName);
        if(!file.exists()){
            throw new VciBaseException("文件未找到,{0}",new String[]{fileName});
        }
        try(InputStream in = new FileInputStream( file);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
        ){
            IOUtils.copy(in,os);
            return os.toByteArray();
        }catch (Throwable e){
            throw new VciBaseException("读取文件的内容出现了错误",new String[0],e);
        }
    }
    /**
     * å†™å…¥å­—符串到文件
     * @param content å­—符串
     * @param fileName æ–‡ä»¶çš„名称
     * @throws VciBaseException å†™å…¥å‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static void writeContentToFile(String content,String fileName) throws VciBaseException{
        File file = new File(fileName);
        if(!file.exists()){
            File parentFile = file.getParentFile();
            if(!parentFile.exists()){
                parentFile.mkdirs();
            }
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new VciBaseException("写入文件的内容时候出现了创建文件失败的问题,{}",new String[]{fileName},e);
            }
        }
        if(content == null){
            content = "";
        }
        try(OutputStream os = new FileOutputStream(file);){
            os.write(content.getBytes(StandardCharsets.UTF_8));
            os.flush();
        }catch(Throwable e){
            throw new VciBaseException("写入文件的内容时候出现了创错误,{}",new String[]{fileName},e);
        }
    }
    /**
     * ä»Žé¡¹ç›®é‡Œæˆ–者jar的文件到目标文件
     * @param fileInJar jar或者项目里的文件名称
     * @param target ç›®æ ‡æ–‡ä»¶
     * @throws VciBaseException æ‹·è´æ–‡ä»¶å‡ºçŽ°é”™è¯¯çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚å¸¸
     */
    public static void copyFileInJar(String fileInJar,String target) throws  VciBaseException{
        alertNotNull(fileInJar,"源文件",target,"目标文件");
        File targetFile = new File(target);
        File folder = targetFile.getParentFile();
        if(!folder.exists()){
            folder.mkdirs();
        }
        if(!targetFile.exists()){
            try {
                targetFile.createNewFile();
            } catch (IOException e) {
                throw new VciBaseException("创建目标文件的出现了错误",new String[0],e);
            }
        }
        if(!fileInJar.startsWith("/")){
            fileInJar = "/" + fileInJar;
        }
        InputStream in = null;
        FileOutputStream os = null;
        try{
            in =  FileUtil.class.getResourceAsStream( fileInJar);
            if(in ==null){
                in=Thread.currentThread().getContextClassLoader().getResourceAsStream(fileInJar);
            }
            os = new FileOutputStream(target);
            IOUtils.copy(in,os);
        }catch (Throwable e){
            throw new VciBaseException("拷贝文件的内容出现了错误.{0},{1}",new String[]{fileInJar,target},e);
        }finally {
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * æ–‡ä»¶è½¬æ¢ä¸ºè·¯å¾„
     * @param fileList æ–‡ä»¶åˆ—表
     * @return è·¯å¾„列表
     * @throws VciBaseException å‚数为空和文件不存在会抛出异常
     */
    public static List<String> fileToPatch(Collection<File> fileList) throws VciBaseException  {
        alertNotNull("文件列表",fileList);
        List<String> filePath = new ArrayList<>();
        for(File file : fileList){
            if(!file.exists()){
                throw new VciBaseException(file.getAbsolutePath() + "文件没有找到",new String[0]);
            }
            filePath.add(file.getAbsolutePath());
        }
        return filePath;
    }
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/utils/ZipUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,155 @@
package com.vci.ubcs.resource.utils;
import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.web.util.LangBaseUtil;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
 * zip相关的工具类
 * @author wanghong
 * @date 2021-02-02
 */
@Component
public class ZipUtil {
    /**
     * èŽ·å–zip的字符集
     * @return é»˜è®¤ä¸ºGBK,否则需要配置
     */
    private String getZipCharset(){
        return (File.separatorChar=='\\')?"GBK":"UTF-8";
    }
    /**
     * å°†æ–‡ä»¶å¤¹åŽ‹ç¼©æˆåŽ‹ç¼©åŒ…
     * @param folder æ–‡ä»¶å¤¹è·¯å¾„
     * @param zipFileName zip文件名
     * @throws VciBaseException å‚数为空或者添加出错的会抛出异常
     */
    public void folderToZipFile(String folder, String zipFileName) throws VciBaseException {
        folderToZipFile(folder,zipFileName,getZipCharset());
    }
    /**
     * å°†æ–‡ä»¶å¤¹åŽ‹ç¼©æˆåŽ‹ç¼©åŒ…
     * @param folder æ–‡ä»¶å¤¹è·¯å¾„
     * @param zipFileName zip文件名
     * @param zipEncode zip的字符集,windows应该为GBK
     * @throws VciBaseException å‚数为空或者添加出错的会抛出异常
     */
    public void folderToZipFile(String folder, String zipFileName,String zipEncode) throws VciBaseException{
        File sourceFile = new File(folder);
        if(!sourceFile.exists()){
            throw new VciBaseException("文件{0}没有找到",new String[]{folder});
        }
        try( ZipOutputStream zos =new ZipOutputStream(new FileOutputStream(zipFileName), StringUtils.hasLength(zipEncode)?Charset.forName(zipEncode): Charset.forName(getZipCharset()));) {
            //默认是UTF-8格式的
            addFileToZip(zos, new File(folder).listFiles(),folder + File.separator);
        }catch (Throwable e){
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e),new String[]{});
        }
    }
    /**
     * å°†æ–‡ä»¶å¤¹åŽ‹ç¼©æˆåŽ‹ç¼©åŒ…
     * @param zos zip输出流
     * @param files è¦åŽ‹ç¼©çš„æ–‡ä»¶
     * @param rootPath åŽ‹ç¼©çš„æ–‡ä»¶ä¸­çš„é¡¶å±‚ç›®å½•
     * @throws VciBaseException æ–‡ä»¶ä¸å­˜åœ¨ï¼Œæˆ–者内容出现错误会抛出异常
     */
    private void addFileToZip(ZipOutputStream zos,File[] files,String rootPath) throws VciBaseException{
        if(files!=null && files.length>0) {
            for (File file : files) {
                if(!StringUtils.hasLength(rootPath)){
                    try {
                        rootPath = file.getParent();
                        if (rootPath == null) {
                            rootPath = file.getPath();
                        }
                    }catch (Throwable e){
                        rootPath = file.getPath();
                    }
                }
                if (!file.exists()) {
                    throw new VciBaseException("文件{0}没有找到",new String[]{file.getAbsolutePath()});
                }
                if (file.isDirectory()) {
                    addFileToZip(zos, file.listFiles(),rootPath);
                }else{
                    try (InputStream is = new FileInputStream(file); ){
                        String entryName = file.getAbsolutePath().replace(rootPath,"");
                        if(entryName.startsWith("\\")) {
                            entryName = entryName.substring(1);
                        }
                        ZipEntry zipEntry = new ZipEntry(entryName);
                        zos.putNextEntry(zipEntry);
                        byte[] b = new byte[100];
                        int length = 0;
                        while ((length = is.read(b)) != -1) {
                            zos.write(b, 0, length);
                        }
                    } catch (Exception e) {
                        throw new VciBaseException("ZIP压缩出错{0}",new String[]{file.getAbsolutePath()},e);
                    }
                }
            }
        }
    }
    /**
     * å°†å•个文件添加到zip中
     * @param file æ–‡ä»¶
     * @param zipFile zip文件
     * @throws VciBaseException å‚数为空或者添加出错的会抛出异常
     */
    public void addFileToZip(File file, String zipFile) throws VciBaseException{
        if(file == null || !file.exists() ){
            throw new VciBaseException("文件{0}没有找到" ,new String[]{file.getAbsolutePath()});
        }
        if(!StringUtils.hasLength(zipFile)){
            throw new VciBaseException("zip文件{0}为空",new String[0]);
        }
        addFileToZip(new File[]{file},zipFile);
    }
    /**
     * å°†å¤šä¸ªä¸ªæ–‡ä»¶æ·»åŠ åˆ°zip中
     * @param files æ–‡ä»¶
     * @param zipFile zip文件
     * @throws VciBaseException å‚数为空或者添加出错的会抛出异常
     */
    public void addFileToZip(File[] files, String zipFile) throws VciBaseException{
       addFileToZip(files, zipFile,getZipCharset());
    }
    /**
     * å°†å¤šä¸ªä¸ªæ–‡ä»¶æ·»åŠ åˆ°zip中
     * @param files æ–‡ä»¶
     * @param zipFile zip文件
     * @param zipEncode zip的字符集
     * @throws VciBaseException å‚数为空或者添加出错的会抛出异常
     */
    public void addFileToZip(File[] files, String zipFile,String zipEncode) throws VciBaseException{
        if(files == null || files.length == 0){
            throw new VciBaseException("文件{0}内容是空",new String[0]);
        }
        if(!StringUtils.hasLength(zipFile)){
            throw new VciBaseException("zip文件{0}是空",new String[0]);
        }
        try (ZipOutputStream zos =new ZipOutputStream(new FileOutputStream(zipFile), StringUtils.hasLength(zipEncode)?Charset.forName(zipEncode): Charset.forName(getZipCharset()));){
            addFileToZip(zos, files,"");
        }catch (Throwable e){
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e),new String[]{},e);
        }
    }
}
Source/UBCS/ubcs-ops-api/ubcs-resource-api/src/main/java/com/vci/ubcs/resource/vo/FileObjectVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
package com.vci.ubcs.resource.vo;
import com.vci.ubcs.resource.entity.FileObject;
import lombok.Data;
/**
 * æ–‡ä»¶çš„æ˜¾ç¤ºå¯¹è±¡
 * @author weidy
 * @date 2023/6/9
 */
@Data
public class FileObjectVO extends FileObject {
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = 2685482161288133481L;
}
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/controller/AttachController.java
@@ -38,6 +38,8 @@
/**
 * é™„件表 æŽ§åˆ¶å™¨
 *
 *
 *
 * @author Chill
 */
@NonDS
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/controller/FileController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,170 @@
package com.vci.ubcs.resource.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.vci.ubcs.resource.dto.FileObjectDTO;
import com.vci.ubcs.resource.dto.FileReleaseDTO;
import com.vci.ubcs.resource.dto.FileShareDTO;
import com.vci.ubcs.resource.query.FileQuery;
import com.vci.ubcs.resource.service.IFileService;
import com.vci.ubcs.resource.utils.FileDownloadUtil;
import com.vci.ubcs.resource.vo.FileObjectVO;
import com.vci.ubcs.starter.web.util.LangBaseUtil;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import org.springblade.core.mp.support.Query;
import org.springblade.core.oss.MinioTemplate;
import org.springblade.core.tool.api.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.List;
/**
 * æ–‡ä»¶æŽ§åˆ¶å™¨
 * @author weidy
 * @date 2023-6/9
 */
@RestController()
@RequestMapping("/fileController")
public class FileController {
    /**
     * æ–‡ä»¶æœåŠ¡
     */
    @Autowired
    private IFileService fileService;
    /**
     * minio的配置
     */
    @Autowired
    private MinioTemplate minioTemplate;
    /**
     * æ ¹æ®æ–‡ä»¶ä¸»é”®ä¸‹è½½æ–‡ä»¶
     * @param fileOids æ–‡ä»¶çš„主键
     * @param response å“åº”的对象
     * @return æ‰§è¡Œç»“果,只有下载失败的时候才会这样
     */
    @RequestMapping(value = "/downloadFilesByOids",method = {RequestMethod.GET,RequestMethod.POST})
    public R downloadFilesByOids(@RequestParam String fileOids, HttpServletResponse response){
        try{
            FileDownloadUtil.downloadFile(response, fileService.downloadFileByOids(VciBaseUtil.str2List(fileOids)));
        }catch (Throwable e){
            return R.fail(LangBaseUtil.getErrorMsg(e));
        }
        return R.success("下载完成");
    }
    /**
     * æ–‡ä»¶åˆ é™¤
     * @param oids æ–‡ä»¶çš„主键
     * @return æ–‡ä»¶å†…容
     */
    @DeleteMapping("/deleteFile")
    public R deleteFile(@RequestBody Collection<String> oids){
        fileService.deleteFiles(oids);
        return R.success("删除成功");
    }
    /**
     * å‰ç«¯é¡µé¢å•文件上传。(先数据,后文件模式上传)
     * @param file ä¸Šä¼ çš„æ–‡ä»¶
     * @param fileObjectDTO æ–‡ä»¶ä¿¡æ¯ä¼ è¾“对象
     * @return æ–‡ä»¶ä¿¡æ¯æ˜¾ç¤ºå¯¹è±¡
     */
    @PostMapping("/uploadFile")
    public R<FileObjectVO> uploadFile(MultipartFile file, FileObjectDTO fileObjectDTO){
        if (file != null ) {
            return fileService.uploadFile(file, fileObjectDTO);
        } else {
            return R.fail("无上传的文件");
        }
    }
    /**
     * åœ¨ä¸Šä¼ æ–‡ä»¶åŽï¼Œä¿å­˜æ–‡ä»¶çš„信息
     * @param fileObjectDTO æ–‡ä»¶ä¿¡æ¯ä¼ è¾“对象
     * @return æ–‡ä»¶ä¿¡æ¯æ˜¾ç¤ºå¯¹è±¡
     */
    @PostMapping("/saveFileAfterUpload")
    public R<FileObjectVO> saveFileAfterUpload( @RequestBody FileObjectDTO fileObjectDTO){
       return fileService.saveFileAfterUpload(fileObjectDTO);
    }
    /**
     * å°†åŽŸæ•°æ®ä¸‹çš„æ‰€æœ‰æ–‡ä»¶å…±äº«åˆ°å…¶ä»–çš„ä¸šåŠ¡æ•°æ®ä¸‹
     * @param shareDTO æ–‡ä»¶åˆ†äº«
     * @return æ–‡ä»¶ä¿¡æ¯æ˜¾ç¤ºå¯¹è±¡,是多个
     */
    @PostMapping("/shareFiles")
    public R<List<FileObjectVO>> shareFiles(@RequestBody FileShareDTO shareDTO){
        return fileService.shareFiles(shareDTO);
    }
    /**
     * ä¿®æ”¹æ–‡ä»¶ä¿¡æ¯(不含文件),注意objectName和filePath不会变化
     * @param fileDTOs æ–‡ä»¶çš„æ•°æ®å¯¹è±¡
     * @return æ‰§è¡Œç»“æžœ
     */
    @PostMapping("/updateFileInfos")
    public R updateFileInfos(@RequestBody Collection<FileObjectDTO> fileDTOs){
        return fileService.updateFileInfos(fileDTOs);
    }
    /**
     * æ–‡ä»¶ç”Ÿæ•ˆ
     * @param ids æ–‡ä»¶çš„主键
     * @return æ‰§è¡Œç»“æžœ
     */
    @PutMapping("/releasedFiles")
    public R releasedFiles(@RequestBody Collection<String> ids){
        return fileService.releasedFiles(ids);
    }
    /**
     * æ‰¹é‡æŒ‡å®šæ–‡ä»¶ä¸šåŠ¡æ•°æ®åŽç”Ÿæ•ˆ
     * @param releaseDTOS ç”Ÿæ•ˆçš„相关信息
     * @return æ‰§è¡Œç»“æžœ
     */
    @PutMapping("/releasedFilesForOwn")
    public R releasedFilesForOwn(@RequestBody Collection<FileReleaseDTO> releaseDTOS){
        return fileService.releasedFilesForOwn(releaseDTOS);
    }
    /**
     * ä½¿ç”¨ä¸šåŠ¡ç±»åž‹æŸ¥è¯¢æ–‡ä»¶çš„ä¿¡æ¯ï¼Œæä¾›ç»™é¡µé¢è°ƒç”¨
     * @param fileQuery æŸ¥è¯¢å¯¹è±¡
     * @return æ–‡ä»¶çš„æ˜¾ç¤ºå¯¹è±¡
     */
    @RequestMapping(value = "/listFiles",method = {RequestMethod.GET,RequestMethod.POST})
    public R<IPage<FileObjectVO>> listFiles(FileQuery fileQuery, Query query){
        return R.data(fileService.listFiles(fileQuery,query));
    }
    /**
     * ä½¿ç”¨æ–‡ä»¶ä¸»é”®èŽ·å–å¯¹è±¡
     * @param oid ä¸»é”®
     * @return æ–‡ä»¶æ˜¾ç¤ºå¯¹è±¡
     */
    @GetMapping("/get")
    public FileObjectVO get(String oid){
        return fileService.get(oid);
    }
    /**
     * ä½¿ç”¨æ–‡ä»¶çš„主键批量获取对象
     * @param oids æ–‡ä»¶çš„主键集合
     * @return æ–‡ä»¶çš„æ˜¾ç¤ºä¿¡æ¯
     */
    @GetMapping("/listFilesByOids")
    public List<FileObjectVO> listFilesByOids( Collection<String> oids){
        return fileService.listFilesByOids(oids);
    }
}
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/endpoint/OssEndpoint.java
@@ -17,6 +17,10 @@
package com.vci.ubcs.resource.endpoint;
import com.vci.ubcs.resource.entity.Attach;
import com.vci.ubcs.resource.service.IFileService;
import com.vci.ubcs.resource.utils.FileDownloadUtil;
import com.vci.ubcs.starter.web.util.LangBaseUtil;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
@@ -28,11 +32,16 @@
import org.springblade.core.tool.utils.Func;
import com.vci.ubcs.resource.builder.oss.OssBuilder;
import com.vci.ubcs.resource.service.IAttachService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
/**
 * å¯¹è±¡å­˜å‚¨ç«¯ç‚¹
 *
 * è¿™ä¸ªç±»ä¸ä½¿ç”¨ï¼Œç»Ÿä¸€ç”¨fileController
 *
 * @author Chill
 */
@@ -41,6 +50,7 @@
@AllArgsConstructor
@RequestMapping("/oss/endpoint")
@Api(value = "对象存储端点", tags = "对象存储端点")
@Deprecated
public class OssEndpoint {
    /**
@@ -52,6 +62,7 @@
     * é™„件表服务
     */
    private final IAttachService attachService;
    /**
     * åˆ›å»ºå­˜å‚¨æ¡¶
@@ -68,7 +79,7 @@
    }
    /**
     * åˆ›å»ºå­˜å‚¨æ¡¶
     * åˆ é™¤å­˜å‚¨æ¡¶
     *
     * @param bucketName å­˜å‚¨æ¡¶åç§°
     * @return R
@@ -107,6 +118,7 @@
    public R<OssFile> statFile(@RequestParam String fileName) {
        return R.data(ossBuilder.template().statFile(fileName));
    }
    /**
     * èŽ·å–æ–‡ä»¶ç›¸å¯¹è·¯å¾„
@@ -160,37 +172,37 @@
        return R.data(bladeFile);
    }
    /**
     * ä¸Šä¼ æ–‡ä»¶å¹¶ä¿å­˜è‡³é™„件表
     *
     * @param file æ–‡ä»¶
     * @return ObjectStat
     */
    @SneakyThrows
    @PostMapping("/put-file-attach")
    public R<BladeFile> putFileAttach(@RequestParam MultipartFile file) {
        String fileName = file.getOriginalFilename();
        BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream());
        Long attachId = buildAttach(fileName, file.getSize(), bladeFile);
        bladeFile.setAttachId(attachId);
        return R.data(bladeFile);
    }
//    /**
//     * ä¸Šä¼ æ–‡ä»¶å¹¶ä¿å­˜è‡³é™„件表
//     *
//     * @param file æ–‡ä»¶
//     * @return ObjectStat
//     */
//    @SneakyThrows
//    @PostMapping("/put-file-attach")
//    public R<BladeFile> putFileAttach(@RequestParam MultipartFile file) {
//        String fileName = file.getOriginalFilename();
//        BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream());
//        Long attachId = buildAttach(fileName, file.getSize(), bladeFile);
//        bladeFile.setAttachId(attachId);
//        return R.data(bladeFile);
//    }
    /**
     * ä¸Šä¼ æ–‡ä»¶å¹¶ä¿å­˜è‡³é™„件表
     *
     * @param fileName å­˜å‚¨æ¡¶å¯¹è±¡åç§°
     * @param file     æ–‡ä»¶
     * @return ObjectStat
     */
    @SneakyThrows
    @PostMapping("/put-file-attach-by-name")
    public R<BladeFile> putFileAttach(@RequestParam String fileName, @RequestParam MultipartFile file) {
        BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream());
        Long attachId = buildAttach(fileName, file.getSize(), bladeFile);
        bladeFile.setAttachId(attachId);
        return R.data(bladeFile);
    }
//    /**
//     * ä¸Šä¼ æ–‡ä»¶å¹¶ä¿å­˜è‡³é™„件表
//     *
//     * @param fileName å­˜å‚¨æ¡¶å¯¹è±¡åç§°
//     * @param file     æ–‡ä»¶
//     * @return ObjectStat
//     */
//    @SneakyThrows
//    @PostMapping("/put-file-attach-by-name")
//    public R<BladeFile> putFileAttach(@RequestParam String fileName, @RequestParam MultipartFile file) {
//        BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream());
//        Long attachId = buildAttach(fileName, file.getSize(), bladeFile);
//        bladeFile.setAttachId(attachId);
//        return R.data(bladeFile);
//    }
    /**
     * æž„建附件表
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/mapper/FileObjectMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
package com.vci.ubcs.resource.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.vci.ubcs.resource.entity.FileObject;
/**
 * æ–‡ä»¶çš„æ•°æ®æ“ä½œç±»
 * @author weidy
 * @date 2023/6/9
 */
public interface FileObjectMapper extends BaseMapper<FileObject> {
}
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/service/IFileService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,111 @@
package com.vci.ubcs.resource.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vci.ubcs.resource.bo.FileObjectBO;
import com.vci.ubcs.resource.dto.FileObjectDTO;
import com.vci.ubcs.resource.dto.FileReleaseDTO;
import com.vci.ubcs.resource.dto.FileShareDTO;
import com.vci.ubcs.resource.entity.FileObject;
import com.vci.ubcs.resource.query.FileQuery;
import com.vci.ubcs.resource.vo.FileObjectVO;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.util.Collection;
import java.util.List;
/**
 * æ–‡ä»¶çš„æœåŠ¡
 * @author weidy
 * @date 2023/1/31
 */
public interface IFileService extends IService<FileObject> {
    /**
     * ä¸‹è½½ï¼Œæ³¨æ„å¤šä¸ªæ–‡ä»¶çš„æ—¶å€™ï¼Œä¼šè‡ªåŠ¨ä¸‹è½½ä¸ºä¸€ä¸ªåŽ‹ç¼©åŒ…
     * @param oids ä¸»é”®é›†åˆ
     * @return æ–‡ä»¶çš„信息
     */
    FileObjectBO downloadFileByOids(Collection<String> oids);
    /**
     * åˆ é™¤æ–‡ä»¶
     * @param oids ä¸»é”®é›†åˆ
     * @return æ‰§è¡Œç»“æžœ
     */
    void deleteFiles(Collection<String> oids);
    /**
     * ä¸Šä¼ æ–‡ä»¶
     * @param file æ–‡ä»¶çš„信息
     * @param fileObjectDTO æ–‡ä»¶çš„相关信息
     * @return æ–‡ä»¶ä¸Šä¼ åŽçš„信息
     */
    R<FileObjectVO> uploadFile(MultipartFile file, FileObjectDTO fileObjectDTO);
    /**
     * ä¿®æ”¹æ–‡ä»¶çš„信息(不会改objectName和filePath)
     * @param fileDTOs æ–‡ä»¶çš„信息
     * @return ä¿®æ”¹åŽçš„信息
     */
    R<List<FileObjectVO>> updateFileInfos(Collection<FileObjectDTO> fileDTOs);
    FileObjectVO do2Vo(FileObject fileObject);
    List<FileObjectVO> do2Vos(Collection<FileObject> fileObjects);
    /**
     * åˆ†äº«æ–‡ä»¶åˆ°å…¶ä»–数据中
     *
     * @param shareDTO æ¥æºä¸šåŠ¡
     * @return åˆ†äº«åŽçš„æ–‡ä»¶ä¿¡æ¯
     */
    R<List<FileObjectVO>> shareFiles(FileShareDTO shareDTO);
    /**
     * æ–‡ä»¶åˆ—表查询
     * @param fileQuery æ–‡ä»¶æŸ¥è¯¢
     * @param query åˆ†é¡µæŸ¥è¯¢å¯¹è±¡
     * @return æ–‡ä»¶çš„æ˜¾ç¤ºä¿¡æ¯
     */
    IPage<FileObjectVO> listFiles(FileQuery fileQuery, Query query);
    /**
     * ä½¿ç”¨æ–‡ä»¶çš„主键批量获取对象
     * @param oids æ–‡ä»¶çš„主键集合
     * @return æ–‡ä»¶çš„æ˜¾ç¤ºä¿¡æ¯
     */
    List<FileObjectVO> listFilesByOids(Collection<String> oids);
    /**
     * æ–‡ä»¶ç”Ÿæ•ˆ
     * @param oids ä¸»é”®é›†åˆ
     * @return æ‰§è¡Œç»“æžœ
     */
    R releasedFiles(Collection<String> oids);
    /**
     * æ‰¹é‡æŒ‡å®šæ–‡ä»¶ä¸šåŠ¡æ•°æ®åŽç”Ÿæ•ˆ
     * @param releaseDTOS ç”Ÿæ•ˆçš„相关信息
     * @return æ‰§è¡Œç»“æžœ
     */
    R releasedFilesForOwn(Collection<FileReleaseDTO> releaseDTOS);
    /**
     * åœ¨ä¸Šä¼ æ–‡ä»¶åŽï¼Œä¿å­˜æ–‡ä»¶çš„信息
     * @param fileObjectDTO æ–‡ä»¶ä¿¡æ¯ä¼ è¾“对象
     * @return æ–‡ä»¶ä¿¡æ¯æ˜¾ç¤ºå¯¹è±¡
     */
    R<FileObjectVO> saveFileAfterUpload(FileObjectDTO fileObjectDTO);
    /**
     * èŽ·å–å¯¹è±¡
     * @param oid ä¸»é”®
     * @return æ–‡ä»¶çš„æ˜¾ç¤ºå¯¹è±¡
     */
    FileObjectVO get(String oid);
}
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/service/impl/FileServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,536 @@
package com.vci.ubcs.resource.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vci.ubcs.resource.bo.FileObjectBO;
import com.vci.ubcs.resource.dto.FileObjectDTO;
import com.vci.ubcs.resource.dto.FileReleaseDTO;
import com.vci.ubcs.resource.dto.FileShareDTO;
import com.vci.ubcs.resource.entity.Attach;
import com.vci.ubcs.resource.entity.FileObject;
import com.vci.ubcs.resource.life.FileLife;
import com.vci.ubcs.resource.mapper.FileObjectMapper;
import com.vci.ubcs.resource.query.FileQuery;
import com.vci.ubcs.resource.service.IFileService;
import com.vci.ubcs.resource.utils.FileUtil;
import com.vci.ubcs.resource.utils.ZipUtil;
import com.vci.ubcs.resource.vo.FileObjectVO;
import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.web.enumpck.BaseEnum;
import com.vci.ubcs.starter.web.enumpck.UserSecretEnum;
import com.vci.ubcs.starter.web.util.BeanUtil;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.oss.MinioTemplate;
import org.springblade.core.oss.OssTemplate;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.oss.model.OssFile;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
/**
 * æ–‡ä»¶æœåŠ¡
 * @author weidy
 * @date 2023/2/1
 */
@Service
@Slf4j
public class FileServiceImpl extends ServiceImpl<FileObjectMapper, FileObject> implements IFileService {
    /**
     * æ–‡ä»¶çš„æ•°æ®æ“ä½œç±»
     */
    @Resource
    private FileObjectMapper fileObjectMapper;
    /**
     * å¯¹è±¡çš„æ¨¡ç‰ˆ
     */
    @Autowired
    private OssTemplate ossTemplate;
    /**
     * æ–‡ä»¶æœåŠ¡çš„é…ç½®
     */
    @Autowired
    private OssProperties ossProperties;
    /**
     * åŽ‹ç¼©æ–‡ä»¶çš„å·¥å…·ç±»
     */
    @Autowired
    private ZipUtil zipUtil;
    /***
     * æ–‡ä»¶çš„规则
     */
    @Autowired
    private OssRule ossRule;
    /**
     * ä¸‹è½½ï¼Œæ³¨æ„å¤šä¸ªæ–‡ä»¶çš„æ—¶å€™ï¼Œä¼šè‡ªåŠ¨ä¸‹è½½ä¸ºä¸€ä¸ªåŽ‹ç¼©åŒ…
     *
     * @param oids ä¸»é”®é›†åˆ
     * @return æ–‡ä»¶çš„信息
     */
    @Override
    public FileObjectBO downloadFileByOids(Collection<String> oids) {
        VciBaseUtil.alertNotNull(oids,"文件的主键集合");
        if(log.isDebugEnabled()){
            log.debug("下载文件,",oids.stream().collect(Collectors.joining(",")));
        }
        Collection<FileObjectVO> fileVOs = listFilesByOids(oids);
        FileObjectBO fileObjectBO = new FileObjectBO();
        if(fileVOs.size()==1){
            //只有一个
            FileObjectVO objectVO = fileVOs.stream().findFirst().get();
            BeanUtil.convert(objectVO,fileObjectBO);
            OssFile ossFile = ossTemplate.statFile(objectVO.getBucketName(), objectVO.getObjectName());
            if(ossFile == null || !StringUtils.hasLength(ossFile.getLink())){
                throw new VciBaseException("文件在存储里没有找到",oids.toArray(new String[0]));
            }
            URL url = null;
            try {
                url = new URL(ossFile.getLink());
            } catch (MalformedURLException e) {
                throw new VciBaseException("文件的获取路径有问题",new String[]{ossFile.getLink()},e);
            }
            try {
                fileObjectBO.setInputStream(url.openStream());
            }catch (Throwable e){
                throw new VciBaseException("获取文件的流有问题",new String[]{ossFile.getLink()},e);
            }
        }else{
            //有多个,需要使用zip进行压缩
            String tempFolder = FileUtil.getDefaultTempFolder();
            fileVOs.stream().forEach(fileVO->{
                String fileName = tempFolder + File.separator + fileVO.getName() + "." + fileVO.getFileExtension();
                File file = new File(fileName);
                try {
                    if(!file.exists()) {
                        file.createNewFile();
                    }
                }catch (Throwable e){
                    throw new VciBaseException("创建文件出错,{0}",new String[]{fileName});
                }
                OssFile ossFile = ossTemplate.statFile(fileVO.getBucketName(), fileVO.getObjectName());
                if(ossFile == null || !StringUtils.hasLength(ossFile.getLink())){
                    throw new VciBaseException("文件在存储里没有找到",oids.toArray(new String[0]));
                }
                URL url = null;
                try {
                    url = new URL(ossFile.getLink());
                } catch (MalformedURLException e) {
                    throw new VciBaseException("文件的获取路径有问题",new String[]{ossFile.getLink()},e);
                }
                try(OutputStream os = new FileOutputStream(file);
                    InputStream ins = url.openStream();
                ){
                    IOUtils.copy(ins,os);
                }catch (Throwable e){
                    throw new VciBaseException("下载文件到临时文件夹里出错,{0}",new String[]{fileName});
                }
            });
            String zipName = new File(tempFolder).getPath() + File.separator + fileVOs.stream().findFirst().get().getName() + "等"+fileVOs.size() + "个文件.zip";
            zipUtil.folderToZipFile(tempFolder,zipName);
            fileObjectBO.setFileLocalPath(zipName);
            if(log.isDebugEnabled()){
                log.debug("下载文件的信息,",zipName);
            }
        }
        return fileObjectBO;
    }
    /**
     * åˆ é™¤æ–‡ä»¶
     *
     * @param oids ä¸»é”®é›†åˆ
     * @return æ‰§è¡Œç»“æžœ
     */
    @Override
    @Transactional()
    public void deleteFiles(Collection<String> oids) {
        VciBaseUtil.alertNotNull(oids,"文件的主键集合");
        if(log.isDebugEnabled()){
            log.debug("删除文件,",oids.stream().collect(Collectors.joining(",")));
        }
        Collection<FileObject> fileObjects = listByIds(oids);
        if(!CollectionUtils.isEmpty(fileObjects)){
            VciBaseUtil.switchCollectionForOracleIn(fileObjects).stream().forEach(fileDOs->{
                fileObjectMapper.deleteBatchIds(fileDOs.stream().map(FileObject::getId).collect(Collectors.toList()));
            });
            //删除minio里的文件
            fileObjects.parallelStream().forEach(fileObject -> {
                ossTemplate.removeFile(fileObject.getBucketName(),fileObject.getObjectName());
            });
        }
    }
    /**
     * ä¸Šä¼ æ–‡ä»¶
     *
     * @param file          æ–‡ä»¶çš„信息
     * @param fileObjectDTO æ–‡ä»¶çš„相关信息
     * @return æ–‡ä»¶ä¸Šä¼ åŽçš„信息
     */
    @Override
    @Transactional
    public R<FileObjectVO> uploadFile(MultipartFile file, FileObjectDTO fileObjectDTO) {
        VciBaseUtil.alertNotNull(fileObjectDTO,"文件的信息");
        String sourceFileName = file.getOriginalFilename();
        String fileExtension = FileUtil.getFileExtensionByName(sourceFileName);
        String fileNameNoExtension = FileUtil.getFileNameUnHasExtensionByName(sourceFileName);
        if(fileObjectDTO.getUpdateFileFlag()==null || !fileObjectDTO.getUpdateFileFlag()) {
            return R.data(add(fileObjectDTO,file));
        }else{
            //修改,需要先获取
            VciBaseUtil.alertNotNull(fileObjectDTO.getOid(),"文件的主键");
            FileObject fileObject = getById(fileObjectDTO.getOid());
            if (StringUtils.hasLength(fileObjectDTO.getId())) {
                fileObject.setId(fileNameNoExtension);
            }
            fileObject.setName(fileNameNoExtension);
            fileObject.setFileExtension(fileExtension);
            fileObject.setFileSize(file.getSize());
            //以前的信息先获取
            String oldObjectName = fileObject.getObjectName();
            String oldBucketName = fileObject.getBucketName();
            String bucketName = StringUtils.hasLength(fileObjectDTO.getBucketName())?fileObjectDTO.getBucketName():ossProperties.getBucketName();
            BladeFile bladeFile = ossTemplate.putFile(bucketName,file.getOriginalFilename(),file);
            fileObject.setBucketName(bucketName);
            fileObject.setObjectName(bladeFile.getName());
            fileObject.setFileLink(bladeFile.getLink());
            fileObjectMapper.updateById(fileObject);
            //删除以前的
            ossTemplate.removeFile(oldBucketName,oldObjectName);
            if(log.isDebugEnabled()){
                log.debug("修改文件",fileObject.toString(),oldObjectName,oldBucketName);
            }
            FileObjectVO fileObjectVO = do2Vo(fileObject);
            return R.data(fileObjectVO);
        }
    }
    private FileObjectVO add(FileObjectDTO fileObjectDTO,MultipartFile file){
        String sourceFileName = file.getOriginalFilename();
        String fileExtension = FileUtil.getFileExtensionByName(sourceFileName);
        String fileNameNoExtension = FileUtil.getFileNameUnHasExtensionByName(sourceFileName);
        //存储业务数据与文件信息
        FileObject fileObject = new FileObject();
        BeanUtil.convert(fileObjectDTO, fileObject);
        if (!StringUtils.hasLength(fileObject.getId())) {
            fileObject.setId(fileNameNoExtension);
        }
        if (!StringUtils.hasLength(fileObject.getName())) {
            fileObject.setName(fileNameNoExtension);
        }
        fileObject.setFileExtension(fileExtension);
        fileObject.setFileSize(file.getSize());
        if (!StringUtils.hasLength(fileObject.getOid())) {
            fileObject.setOid(VciBaseUtil.getPk());
        }
        if (fileObjectDTO.getEffect() != null && fileObjectDTO.getEffect()) {
            fileObject.setLcStatus(FileLife.FILE_RELEASE.getValue());
        } else {
            fileObject.setLcStatus(FileLife.TRANS_FINISH.getValue());
        }
        if (fileObject.getSecretGrade() == null || fileObject.getSecretGrade() == 0) {
            // VciBaseUtil.getCurrentUserSecret()还需要处理,在进入服务的时候,根据当前用户的信息获取用户的对象
            fileObject.setSecretGrade( VciBaseUtil.getCurrentUserSecret());
        }
        String bucketName = StringUtils.hasLength(fileObjectDTO.getBucketName())?fileObjectDTO.getBucketName():ossProperties.getBucketName();
        //先存到Minio后再说
        BladeFile bladeFile = ossTemplate.putFile(bucketName,file.getOriginalFilename(),file);
        fileObject.setBucketName(bucketName);
        fileObject.setObjectName(bladeFile.getName());
        fileObject.setFileLink(bladeFile.getLink());
        fileObjectMapper.insert(fileObject);
        if(log.isDebugEnabled()){
            log.debug("新增文件",fileObject.toString());
        }
        FileObjectVO fileObjectVO = do2Vo(fileObject);
        return fileObjectVO;
    }
    /**
     * æ•°æ®å¯¹è±¡è½¬æ˜¾ç¤ºå¯¹è±¡
     * @param fileObject æ–‡ä»¶çš„æ•°æ®å¯¹è±¡
     * @return æ˜¾ç¤ºå¯¹è±¡
     */
    @Override
    public FileObjectVO do2Vo(FileObject fileObject) {
        FileObjectVO fileObjectVO = new FileObjectVO();
        BeanUtil.convert(fileObject,fileObjectVO);
        fileObjectVO.setLcStatusText(BaseEnum.getTextByValue(FileLife.class,fileObjectVO.getLcStatus()));
        //fileObjectVO.setSecretGradeText(UserSecretEnum);
        return fileObjectVO;
    }
    @Override
    public List<FileObjectVO> do2Vos(Collection<FileObject> fileObjects){
        List<FileObjectVO> fileObjectVOList = new ArrayList<>();
        Optional.ofNullable(fileObjects).orElseGet(ArrayList::new).stream().forEach(fo->{
            fileObjectVOList.add(do2Vo(fo));
        });
        return fileObjectVOList;
    }
    /**
     * åˆ†äº«æ–‡ä»¶åˆ°å…¶ä»–数据中
     *
     * @param shareDTO æ¥æºä¸šåŠ¡
     * @return åˆ†äº«åŽçš„æ–‡ä»¶ä¿¡æ¯
     */
    @Override
    @Transactional
    public R<List<FileObjectVO>> shareFiles(FileShareDTO shareDTO) {
        VciBaseUtil.alertNotNull(shareDTO,"分享的信息",shareDTO.getTargetBus(),"目标的业务名称",shareDTO.getTargetBusOid(),"目标的业务数据主键");
        List<FileObject> fileObjectList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(shareDTO.getOids())){
            fileObjectList.addAll(listByIds(shareDTO.getOids()));
        }
        LambdaQueryWrapper<FileObject> queryWrapper = new LambdaQueryWrapper<FileObject>(FileObject.class);
        if(StringUtils.hasLength(shareDTO.getSourceBus())) {
            queryWrapper.in(FileObject::getOwnBtmName, VciBaseUtil.str2List(shareDTO.getSourceBus()));
        }
        if(StringUtils.hasLength(shareDTO.getSourceBusOid())){
            queryWrapper.in(FileObject::getOwnbizOid,VciBaseUtil.str2List(shareDTO.getSourceBusOid()));
        }
        fileObjectList.addAll(fileObjectMapper.selectList(queryWrapper));
        if(CollectionUtils.isEmpty(fileObjectList)){
            throw new VciBaseException("没有找到可以分享的文件");
        }
        BladeUser user = AuthUtil.getUser();
        Date now = new Date();
        List<FileObject> newFileObjects = new ArrayList<>();
        fileObjectList.stream().forEach(fileObject -> {
            FileObject newFileObject = new FileObject();
            BeanUtil.convert(fileObject,newFileObject);
            newFileObject.setId(VciBaseUtil.getPk());
            newFileObject.setNameOid(VciBaseUtil.getPk());
            newFileObject.setRevisionOid(VciBaseUtil.getPk());
            newFileObject.setCreator(user.getAccount());
            newFileObject.setCreateTime(now);
            newFileObject.setLastModifier(user.getAccount());
            newFileObject.setLastModifyTime(now);
            newFileObject.setTs(now);
            newFileObject.setOwnBtmName(shareDTO.getTargetBus());
            newFileObject.setOwnbizOid(shareDTO.getTargetBusOid());
            newFileObject.setObjectName(ossRule.fileName( "." + fileObject.getFileExtension()));
            //下载文件后,上传文件
            ossTemplate.copyFile(fileObject.getBucketName(),fileObject.getObjectName(),fileObject.getBucketName(),newFileObject.getObjectName());
            newFileObject.setFileLink(ossTemplate.fileLink(newFileObject.getBucketName(),newFileObject.getObjectName()));
            newFileObjects.add(newFileObject);
        });
        newFileObjects.stream().forEach(fileObject -> {
            fileObjectMapper.insert(fileObject);
        });
        return R.data(do2Vos(newFileObjects));
    }
    /**
     * ä¿®æ”¹æ–‡ä»¶çš„信息(不会改objectName和filePath)
     *
     * @param fileDTOs æ–‡ä»¶çš„信息
     * @return ä¿®æ”¹åŽçš„信息
     */
    @Override
    @Transactional
    public R<List<FileObjectVO>> updateFileInfos(Collection<FileObjectDTO> fileDTOs) {
        VciBaseUtil.alertNotNull(fileDTOs,"要更新的文件的信息");
        if(fileDTOs.stream().anyMatch(s->!StringUtils.hasLength(s.getId()))){
            throw new VciBaseException("要更新的文件信息的主键不能为空");
        }
        Map<String, FileObject> fileObjectMap = Optional.ofNullable(listByIds(fileDTOs.stream().map(FileObjectDTO::getId).collect(Collectors.toList()))).orElseGet(ArrayList::new).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t, (o1, o2) -> o1));
        BladeUser user = AuthUtil.getUser();
        Date now = new Date();
        fileDTOs.stream().forEach(fileDTO->{
            if(!fileObjectMap.containsKey(fileDTO.getOid())){
                throw new VciBaseException("名称为{0}的文件在系统里不存在",new String[]{StringUtils.hasLength(fileDTO.getId())?fileDTO.getId():fileDTO.getName()});
            }
            FileObject fileObject = fileObjectMap.get(fileDTO.getId());
            String oldObjectName = fileObject.getObjectName();
            String oldBucketName = fileObject.getBucketName();
            String filePath = fileObject.getFileLink();
            BeanUtil.convert(fileDTO,fileObject);
            fileObject.setObjectName(oldObjectName);
            fileObject.setBucketName(oldBucketName);
            fileObject.setFileLink(filePath);
            fileObject.setLastModifier(user.getAccount());
            fileObject.setLastModifyTime(now);
            fileObject.setTs(now);
        });
       fileObjectMap.values().stream().forEach(fileObject -> {
           fileObjectMapper.updateById(fileObject);
        });
        return R.data(do2Vos(fileObjectMap.values()));
    }
    /**
     * æ–‡ä»¶åˆ—表查询
     *
     * @param fileQuery æ–‡ä»¶æŸ¥è¯¢
     * @return æ–‡ä»¶çš„æ˜¾ç¤ºä¿¡æ¯
     */
    @Override
    public IPage<FileObjectVO> listFiles(FileQuery fileQuery, Query query){
        IPage<FileObject> pages = page(Condition.getPage(query), Condition.getQueryWrapper(fileQuery));
        return pages.convert((fileObject -> do2Vo(fileObject)));
    }
    /**
     * ä½¿ç”¨æ–‡ä»¶çš„主键批量获取对象
     *
     * @param oids æ–‡ä»¶çš„主键集合
     * @return æ–‡ä»¶çš„æ˜¾ç¤ºä¿¡æ¯
     */
    @Override
    public List<FileObjectVO> listFilesByOids(Collection<String> oids) {
        return do2Vos(listByIds(oids));
    }
    /**
     * æ–‡ä»¶ç”Ÿæ•ˆ
     *
     * @param oids ä¸»é”®é›†åˆ
     * @return æ‰§è¡Œç»“æžœ
     */
    @Override
    @Transactional
    public R releasedFiles(Collection<String> oids) {
        Collection<FileObject> fileObjects = listByIds(oids);
        if(!CollectionUtils.isEmpty(fileObjects)){
            fileObjects.stream().forEach(obj->{
                obj.setLcStatus(FileLife.FILE_RELEASE.getValue());
                fileObjectMapper.updateById(obj);
            });
        }
        return R.success("生效成功");
    }
    /**
     * æ‰¹é‡æŒ‡å®šæ–‡ä»¶ä¸šåŠ¡æ•°æ®åŽç”Ÿæ•ˆ
     *
     * @param releaseDTOS ç”Ÿæ•ˆçš„相关信息
     * @return æ‰§è¡Œç»“æžœ
     */
    @Override
    @Transactional
    public R releasedFilesForOwn(Collection<FileReleaseDTO> releaseDTOS) {
        VciBaseUtil.alertNotNull(releaseDTOS,"发布的信息");
        List<FileObject> fileObjectList = new ArrayList<>();
        List<String> oids = new ArrayList<>();
        releaseDTOS.stream().filter(s->!CollectionUtils.isEmpty(s.getOids())).forEach(dtos->{
            oids.addAll(dtos.getOids());
        });
        if(!CollectionUtils.isEmpty(oids)){
            fileObjectList.addAll(listByIds(oids));
        }
        releaseDTOS.stream().forEach(dto->{
            LambdaQueryWrapper<FileObject> queryWrapper =   new LambdaQueryWrapper<>(FileObject.class);
            if(StringUtils.hasLength(dto.getOwnBtmName())) {
                queryWrapper.in(FileObject::getOwnBtmName, VciBaseUtil.str2List(dto.getOwnBtmName()));
            }
            if(StringUtils.hasLength(dto.getOwnbizOid())) {
                queryWrapper.in(FileObject::getOwnbizOid, VciBaseUtil.str2List(dto.getOwnbizOid()));
            }
            fileObjectList.addAll(fileObjectMapper.selectList(queryWrapper));
        });
        if(!CollectionUtils.isEmpty(fileObjectList)){
            fileObjectList.stream().forEach(objs->{
                objs.setLcStatus(FileLife.FILE_RELEASE.getValue());
                fileObjectMapper.updateById(objs);
            });
        }
        return R.success("生效成功");
    }
    /**
     * åœ¨ä¸Šä¼ æ–‡ä»¶åŽï¼Œä¿å­˜æ–‡ä»¶çš„信息
     *
     * @param fileObjectDTO æ–‡ä»¶ä¿¡æ¯ä¼ è¾“对象
     * @return æ–‡ä»¶ä¿¡æ¯æ˜¾ç¤ºå¯¹è±¡
     */
    @Override
    @Transactional
    public R<FileObjectVO> saveFileAfterUpload(FileObjectDTO fileObjectDTO) {
        if(fileObjectDTO.getEffect() !=null && fileObjectDTO.getEffect() && !StringUtils.hasLength(fileObjectDTO.getLcStatus())){
            fileObjectDTO.setLcStatus(FileLife.FILE_RELEASE.getValue());
        }
        return R.data(addOnlyInfo(fileObjectDTO));
    }
    /**
     * èŽ·å–å¯¹è±¡
     *
     * @param oid ä¸»é”®
     * @return æ–‡ä»¶çš„æ˜¾ç¤ºå¯¹è±¡
     */
    @Override
    public FileObjectVO get(String oid) {
        return do2Vo(getById(oid));
    }
    /**
     * ä»…添加信息
     * @param fileObjectDTO æ–‡ä»¶çš„æ•°æ®ä¼ è¾“对象
     * @return æ˜¾ç¤ºå¯¹è±¡
     */
    public FileObjectVO addOnlyInfo(FileObjectDTO fileObjectDTO){
        //存储业务数据与文件信息
        FileObject fileObject = new FileObject();
        BeanUtil.convert(fileObjectDTO, fileObject);
        if (!StringUtils.hasLength(fileObject.getOid())) {
            fileObject.setOid(VciBaseUtil.getPk());
        }
        if (fileObject.getSecretGrade() == null || fileObject.getSecretGrade() == 0) {
            // VciBaseUtil.getCurrentUserSecret()还需要处理,在进入服务的时候,根据当前用户的信息获取用户的对象
            fileObject.setSecretGrade( VciBaseUtil.getCurrentUserSecret());
        }
        fileObjectMapper.insert(fileObject);
        if(log.isDebugEnabled()){
            log.debug("新增文件",fileObject.toString());
        }
        return do2Vo(fileObject);
    }
}
Source/UBCS/ubcs-service-api/ubcs-util-api/src/main/java/com/vci/ubcs/starter/web/enumpck/BaseEnum.java
@@ -1,7 +1,55 @@
package com.vci.ubcs.starter.web.enumpck;
import com.alibaba.druid.util.StringUtils;
public interface BaseEnum {
    String getValue();
    String getText();
    /**
     * ä½¿ç”¨æžšä¸¾çš„值获取枚举对象的通用方法
     * @param clazz æžšä¸¾æ‰€å±žç±»
     * @param value æžšä¸¾çš„值
     * @param <T> ç±»åž‹
     * @return ç»“æžœ
     */
    public static  <T extends BaseEnum> T getEnumByValue(Class<T> clazz,Object value){
        if(value == null){
            return null;
        }
        T[] enums = clazz.getEnumConstants();
        if (enums == null || enums.length == 0) {
            return null;
        }
        for (T e : enums) {
            if (value instanceof String) {
                if (StringUtils.equalsIgnoreCase((String) value, (String) ((BaseEnum) e).getValue())) {
                    return e;
                }
            } else {
                if (value.equals(e.getValue())) {
                    return e;
                }
            }
        }
        return null;
    }
    /**
     * ä½¿ç”¨æžšä¸¾çš„值获取显示文本的方法
     * @param clazz æžšä¸¾æ‰€å±žçš„ç±»
     * @param value æžšä¸¾çš„值
     * @param <T> ç±»åž‹
     * @return ç»“æžœ
     */
    public static <T extends BaseEnum> String getTextByValue(Class<T> clazz,String value){
        T e = getEnumByValue(clazz, value);
        if (e == null) {
            return "";
        }
        return ((BaseEnum) e).getText();
    }
}