mirror of https://gitee.com/stylefeng/roses
【file】更新file
parent
1e318b4faf
commit
5f7fb1f1ad
|
@ -92,7 +92,7 @@ public enum FileExceptionEnum implements AbstractExceptionEnum {
|
|||
/**
|
||||
* 文件不允许被访问
|
||||
*/
|
||||
FILE_DENIED_ACCESS(RuleConstants.USER_OPERATION_ERROR_TYPE_CODE + FileConstants.FILE_EXCEPTION_STEP_CODE + "16", "文件不允许被访问!");
|
||||
FILE_DENIED_ACCESS(RuleConstants.USER_OPERATION_ERROR_TYPE_CODE + FileConstants.FILE_EXCEPTION_STEP_CODE + "16", "文件不允许被访问,文件加密等级不符合");
|
||||
|
||||
/**
|
||||
* 错误编码
|
||||
|
|
|
@ -1,38 +1,44 @@
|
|||
package cn.stylefeng.roses.kernel.file.modular.controller;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.stylefeng.roses.kernel.file.exception.FileException;
|
||||
import cn.stylefeng.roses.kernel.file.exception.enums.FileExceptionEnum;
|
||||
import cn.stylefeng.roses.kernel.file.expander.FileConfigExpander;
|
||||
import cn.stylefeng.roses.kernel.file.modular.service.SysFileInfoService;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.request.SysFileInfoRequest;
|
||||
import cn.stylefeng.roses.kernel.file.util.DownloadUtil;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.response.SysFileInfoResponse;
|
||||
import cn.stylefeng.roses.kernel.resource.api.annotation.ApiResource;
|
||||
import cn.stylefeng.roses.kernel.resource.api.annotation.GetResource;
|
||||
import cn.stylefeng.roses.kernel.resource.api.annotation.PostResource;
|
||||
import cn.stylefeng.roses.kernel.rule.pojo.request.BaseRequest;
|
||||
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
|
||||
import cn.stylefeng.roses.kernel.rule.pojo.response.ResponseData;
|
||||
import cn.stylefeng.roses.kernel.rule.pojo.response.SuccessResponseData;
|
||||
import cn.stylefeng.roses.kernel.rule.util.HttpServletUtil;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.stylefeng.roses.kernel.file.constants.FileConstants.DEFAULT_AVATAR_FILE_OBJ_NAME;
|
||||
import static cn.stylefeng.roses.kernel.file.constants.FileConstants.FILE_PRIVATE_PREVIEW_URL;
|
||||
import static cn.stylefeng.roses.kernel.file.constants.FileConstants.FILE_PUBLIC_PREVIEW_URL;
|
||||
|
||||
/**
|
||||
* 文件信息管理
|
||||
* <p>
|
||||
* 该模块简要说明:
|
||||
* 1.文件支持版本朔源,每次操作均会产生数据
|
||||
* 2.文件支持版本回滚,升级后可选择某一版本进行回退
|
||||
* <p>
|
||||
* 文件管理接口有两种使用方式:
|
||||
* 1.合同文件场景:文件必须保持原样,合同内容升级不影响已签署合同,业务需要关联文件ID<br>
|
||||
* 文件升级不会对之前的数据造成影响
|
||||
* 2.UI文件场景:文件升级后业务所有关联的文件全部升级,业务需要关联文件CODE<br>
|
||||
* <p>
|
||||
* 可能你今天上线,昨天很丑的banner图变好看了~
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 11:17
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 13:39
|
||||
*/
|
||||
@RestController
|
||||
@ApiResource(name = "文件信息相关接口")
|
||||
|
@ -44,77 +50,160 @@ public class SysFileInfoController {
|
|||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 11:17
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 13:17
|
||||
*/
|
||||
@PostResource(name = "上传文件", path = "/sysFileInfo/upload")
|
||||
public ResponseData upload(@RequestPart("file") MultipartFile file) {
|
||||
Long fileId = sysFileInfoService.uploadFile(file);
|
||||
return new SuccessResponseData(fileId);
|
||||
public ResponseData upload(@RequestPart("file") MultipartFile file, @Validated(SysFileInfoRequest.add.class) SysFileInfoRequest sysFileInfoRequest) {
|
||||
SysFileInfoResponse fileUploadInfoResult = this.sysFileInfoService.uploadFile(file, sysFileInfoRequest);
|
||||
return new SuccessResponseData(fileUploadInfoResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
* 替换文件
|
||||
* <p>
|
||||
* 注意:调用本接口之后还需要调用确认接口,本次替换操作才会生效
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/16 15:34
|
||||
*/
|
||||
@PostResource(name = "替换文件", path = "/sysFileInfo/update")
|
||||
public ResponseData update(@RequestPart("file") MultipartFile file, @Validated(SysFileInfoRequest.edit.class) SysFileInfoRequest sysFileInfoRequest) {
|
||||
SysFileInfoResponse fileUploadInfoResult = this.sysFileInfoService.updateFile(file, sysFileInfoRequest);
|
||||
return new SuccessResponseData(fileUploadInfoResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 版本回退
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/16 15:34
|
||||
*/
|
||||
@PostResource(name = "替换文件", path = "/sysFileInfo/versionBack")
|
||||
public ResponseData versionBack(@Validated(SysFileInfoRequest.versionBack.class) SysFileInfoRequest sysFileInfoRequest) {
|
||||
SysFileInfoResponse fileUploadInfoResult = this.sysFileInfoService.versionBack(sysFileInfoRequest);
|
||||
return new SuccessResponseData(fileUploadInfoResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有文件预览
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 11:29
|
||||
*/
|
||||
@GetResource(name = "下载文件", path = "/sysFileInfo/download")
|
||||
public void download(@Validated(BaseRequest.detail.class) SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
sysFileInfoService.download(sysFileInfoRequest, response);
|
||||
@GetResource(name = "私有文件预览", path = FILE_PRIVATE_PREVIEW_URL)
|
||||
public void priPreview(@Validated(SysFileInfoRequest.detail.class) SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
sysFileInfoRequest.setSecretFlag(YesOrNotEnum.Y.getCode());
|
||||
this.sysFileInfoService.preview(sysFileInfoRequest, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件信息
|
||||
* 公有文件预览
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 13:17
|
||||
*/
|
||||
@GetResource(name = "公有文件预览", path = FILE_PUBLIC_PREVIEW_URL, requiredPermission = false, requiredLogin = false)
|
||||
public void pubPreview(@Validated(SysFileInfoRequest.detail.class) SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
sysFileInfoRequest.setSecretFlag(YesOrNotEnum.N.getCode());
|
||||
this.sysFileInfoService.preview(sysFileInfoRequest, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有文件下载
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 13:17
|
||||
*/
|
||||
@GetResource(name = "私有文件下载", path = "/sysFileInfo/privateDownload")
|
||||
public void privateDownload(@Validated(SysFileInfoRequest.detail.class) SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
sysFileInfoRequest.setSecretFlag(YesOrNotEnum.Y.getCode());
|
||||
this.sysFileInfoService.download(sysFileInfoRequest, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 公有文件下载
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 13:17
|
||||
*/
|
||||
@GetResource(name = "公有文件下载", path = "/sysFileInfo/publicDownload", requiredLogin = false, requiredPermission = false)
|
||||
public void publicDownload(@Validated(SysFileInfoRequest.detail.class) SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
sysFileInfoRequest.setSecretFlag(YesOrNotEnum.N.getCode());
|
||||
this.sysFileInfoService.download(sysFileInfoRequest, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据附件IDS查询附件信息
|
||||
*
|
||||
* @param fileIds 附件IDS
|
||||
* @return 附件返回类
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 13:17
|
||||
*/
|
||||
@GetResource(name = "根据附件IDS查询附件信息", path = "/sysFileInfo/getFileInfoListByFileIds")
|
||||
public ResponseData getFileInfoListByFileIds(@RequestParam(value = "fileIds") String fileIds) {
|
||||
List<SysFileInfoResponse> list = this.sysFileInfoService.getFileInfoListByFileIds(fileIds);
|
||||
return new SuccessResponseData(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 公有打包下载文件
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 13:17
|
||||
*/
|
||||
@GetResource(name = "公有打包下载文件", path = "/sysFileInfo/publicPackagingDownload", requiredPermission = false, requiredLogin = false)
|
||||
public void publicPackagingDownload(@RequestParam(value = "fileIds") String fileIds, HttpServletResponse response) {
|
||||
this.sysFileInfoService.packagingDownload(fileIds, YesOrNotEnum.N.getCode(), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有打包下载文件
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 13:18
|
||||
*/
|
||||
@GetResource(name = "私有打包下载文件", path = "/sysFileInfo/privatePackagingDownload")
|
||||
public void privatePackagingDownload(@RequestParam(value = "fileIds") String fileIds, HttpServletResponse response) {
|
||||
this.sysFileInfoService.packagingDownload(fileIds, YesOrNotEnum.Y.getCode(), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件信息(真删除文件信息)
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 11:19
|
||||
*/
|
||||
@PostResource(name = "删除文件信息", path = "/sysFileInfo/delete")
|
||||
public ResponseData delete(@RequestBody @Validated(SysFileInfoRequest.delete.class) SysFileInfoRequest sysFileInfoRequest) {
|
||||
sysFileInfoService.delete(sysFileInfoRequest);
|
||||
@PostResource(name = "删除文件信息(真删除文件信息)", path = "/sysFileInfo/deleteReally")
|
||||
public ResponseData deleteReally(@RequestBody @Validated(SysFileInfoRequest.delete.class) SysFileInfoRequest sysFileInfoRequest) {
|
||||
this.sysFileInfoService.deleteReally(sysFileInfoRequest);
|
||||
return new SuccessResponseData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件预览
|
||||
* <p>
|
||||
* 支持通过文件id预览,也支持直接通过bucket和obj名称预览
|
||||
* 分页查询文件信息表
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 11:29
|
||||
*/
|
||||
@GetResource(name = "文件预览", path = FILE_PRIVATE_PREVIEW_URL)
|
||||
public void preview(SysFileInfoRequest sysFileInfoRequest) {
|
||||
HttpServletResponse response = HttpServletUtil.getResponse();
|
||||
@GetResource(name = "分页查询文件信息表", path = "/sysFileInfo/fileInfoListPage")
|
||||
public ResponseData fileInfoListPage(SysFileInfoRequest sysFileInfoRequest) {
|
||||
return new SuccessResponseData(this.sysFileInfoService.fileInfoListPage(sysFileInfoRequest));
|
||||
}
|
||||
|
||||
// 请求参数不能为空
|
||||
if (sysFileInfoRequest == null) {
|
||||
String userTip = StrUtil.format(FileExceptionEnum.PREVIEW_EMPTY_ERROR.getUserTip(), "");
|
||||
throw new FileException(FileExceptionEnum.PREVIEW_EMPTY_ERROR, userTip);
|
||||
}
|
||||
|
||||
// 文件是-1则返回系统默认头像
|
||||
if (DEFAULT_AVATAR_FILE_OBJ_NAME.equals(sysFileInfoRequest.getFileObjectName())) {
|
||||
DownloadUtil.renderPreviewFile(response, Base64.decode(FileConfigExpander.getDefaultAvatarBase64()));
|
||||
return;
|
||||
}
|
||||
|
||||
// 文件id不为空,则根据文件id预览
|
||||
if (ObjectUtil.isNotEmpty(sysFileInfoRequest.getFileId())) {
|
||||
sysFileInfoService.previewByFileId(sysFileInfoRequest, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// 文件bucketName和objectName不为空,则根据bucket预览
|
||||
if (ObjectUtil.isAllNotEmpty(sysFileInfoRequest.getFileBucket(), sysFileInfoRequest.getFileObjectName())) {
|
||||
sysFileInfoService.previewByBucketAndObjName(sysFileInfoRequest, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// 提示用户信息不全
|
||||
String userTip = StrUtil.format(FileExceptionEnum.PREVIEW_EMPTY_ERROR.getUserTip(), sysFileInfoRequest);
|
||||
throw new FileException(FileExceptionEnum.PREVIEW_EMPTY_ERROR, userTip);
|
||||
/**
|
||||
* 确认替换附件
|
||||
* <p>
|
||||
* 在替换接口替换文件以后,需要调用本接口替换操作才会生效
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 13:18
|
||||
*/
|
||||
@PostResource(name = "确认替换附件", path = "/sysFileInfo/confirmReplaceFile")
|
||||
public ResponseData confirmReplaceFile(@RequestBody List<Long> fileIdList) {
|
||||
this.sysFileInfoService.confirmReplaceFile(fileIdList);
|
||||
return new SuccessResponseData();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,26 +217,46 @@ public class SysFileInfoController {
|
|||
return new SuccessResponseData(sysFileInfoService.detail(sysFileInfoRequest));
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询文件信息表
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 11:29
|
||||
*/
|
||||
@GetResource(name = "分页查询文件信息表", path = "/sysFileInfo/page")
|
||||
public ResponseData page(SysFileInfoRequest sysFileInfoRequest) {
|
||||
return new SuccessResponseData(sysFileInfoService.page(sysFileInfoRequest));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全部文件信息表
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 11:29
|
||||
*/
|
||||
@GetResource(name = "获取全部文件信息表", path = "/sysFileInfo/list")
|
||||
public ResponseData list(SysFileInfoRequest sysFileInfoRequest) {
|
||||
return new SuccessResponseData(sysFileInfoService.list(sysFileInfoRequest));
|
||||
}
|
||||
// /**
|
||||
// * 文件预览
|
||||
// * <p>
|
||||
// * 支持通过文件id预览,也支持直接通过bucket和obj名称预览
|
||||
// *
|
||||
// * @author fengshuonan
|
||||
// * @date 2020/11/29 11:29
|
||||
// */
|
||||
// @GetResource(name = "文件预览", path = FILE_PRIVATE_PREVIEW_URL)
|
||||
// public void preview(SysFileInfoRequest sysFileInfoRequest) {
|
||||
// HttpServletResponse response = HttpServletUtil.getResponse();
|
||||
//
|
||||
// // 请求参数不能为空
|
||||
// if (sysFileInfoRequest == null) {
|
||||
// String userTip = StrUtil.format(FileExceptionEnum.PREVIEW_EMPTY_ERROR.getUserTip(), "");
|
||||
// throw new FileException(FileExceptionEnum.PREVIEW_EMPTY_ERROR, userTip);
|
||||
// }
|
||||
//
|
||||
// // 文件是-1则返回系统默认头像
|
||||
// if (DEFAULT_AVATAR_FILE_OBJ_NAME.equals(sysFileInfoRequest.getFileObjectName())) {
|
||||
// DownloadUtil.renderPreviewFile(response, Base64.decode(FileConfigExpander.getDefaultAvatarBase64()));
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 文件id不为空,则根据文件id预览
|
||||
// if (ObjectUtil.isNotEmpty(sysFileInfoRequest.getFileId())) {
|
||||
// sysFileInfoService.previewByFileId(sysFileInfoRequest, response);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 文件bucketName和objectName不为空,则根据bucket预览
|
||||
// if (ObjectUtil.isAllNotEmpty(sysFileInfoRequest.getFileBucket(), sysFileInfoRequest.getFileObjectName())) {
|
||||
// sysFileInfoService.previewByBucketAndObjName(sysFileInfoRequest, response);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 提示用户信息不全
|
||||
// String userTip = StrUtil.format(FileExceptionEnum.PREVIEW_EMPTY_ERROR.getUserTip(), sysFileInfoRequest);
|
||||
// throw new FileException(FileExceptionEnum.PREVIEW_EMPTY_ERROR, userTip);
|
||||
// }
|
||||
|
||||
}
|
|
@ -28,11 +28,25 @@ public class SysFileInfo extends BaseEntity {
|
|||
private Long fileId;
|
||||
|
||||
/**
|
||||
* 文件编码,解决一个文件多个版本问题,多次上传文件编码不变
|
||||
* 文件编码,本号升级的依据
|
||||
* <p>
|
||||
* 解决一个文件多个版本问题,多次上传文件编码不变
|
||||
*/
|
||||
@TableField(value = "file_code")
|
||||
@TableField("file_code")
|
||||
private Long fileCode;
|
||||
|
||||
/**
|
||||
* 文件版本,从1开始
|
||||
*/
|
||||
@TableField("file_version")
|
||||
private Integer fileVersion;
|
||||
|
||||
/**
|
||||
* 当前状态:0-历史版,1-最新版
|
||||
*/
|
||||
@TableField("file_status")
|
||||
private String fileStatus;
|
||||
|
||||
/**
|
||||
* 文件存储位置:1-阿里云,2-腾讯云,3-minio,4-本地
|
||||
*/
|
||||
|
@ -63,6 +77,12 @@ public class SysFileInfo extends BaseEntity {
|
|||
@TableField("file_size_kb")
|
||||
private Long fileSizeKb;
|
||||
|
||||
/**
|
||||
* 文件大小信息,计算后的
|
||||
*/
|
||||
@TableField("file_size_info")
|
||||
private String fileSizeInfo;
|
||||
|
||||
/**
|
||||
* 存储到bucket中的名称,主键id+.后缀
|
||||
*/
|
||||
|
@ -75,6 +95,12 @@ public class SysFileInfo extends BaseEntity {
|
|||
@TableField("file_path")
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
* 是否为机密文件
|
||||
*/
|
||||
@TableField("secret_flag")
|
||||
private String secretFlag;
|
||||
|
||||
/**
|
||||
* 是否删除:Y-被删除,N-未删除
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package cn.stylefeng.roses.kernel.file.modular.factory;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.stylefeng.roses.kernel.file.FileOperatorApi;
|
||||
import cn.stylefeng.roses.kernel.file.enums.FileLocationEnum;
|
||||
import cn.stylefeng.roses.kernel.file.enums.FileStatusEnum;
|
||||
import cn.stylefeng.roses.kernel.file.exception.FileException;
|
||||
import cn.stylefeng.roses.kernel.file.exception.enums.FileExceptionEnum;
|
||||
import cn.stylefeng.roses.kernel.file.modular.entity.SysFileInfo;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.request.SysFileInfoRequest;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static cn.stylefeng.roses.kernel.file.constants.FileConstants.DEFAULT_BUCKET_NAME;
|
||||
import static cn.stylefeng.roses.kernel.file.constants.FileConstants.FILE_POSTFIX_SEPARATOR;
|
||||
|
||||
/**
|
||||
* 文件信息组装工厂
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/12/30 22:16
|
||||
*/
|
||||
public class FileInfoFactory {
|
||||
|
||||
/**
|
||||
* 封装附件信息
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 12:55
|
||||
*/
|
||||
public static SysFileInfo createSysFileInfo(MultipartFile file, SysFileInfoRequest sysFileInfoRequest) {
|
||||
|
||||
FileOperatorApi fileOperatorApi = SpringUtil.getBean(FileOperatorApi.class);
|
||||
|
||||
// 生成文件的唯一id
|
||||
Long fileId = IdWorker.getId();
|
||||
|
||||
// 获取文件原始名称
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
|
||||
// 获取文件后缀(不包含点)
|
||||
String fileSuffix = null;
|
||||
if (ObjectUtil.isNotEmpty(originalFilename)) {
|
||||
fileSuffix = StrUtil.subAfter(originalFilename, FILE_POSTFIX_SEPARATOR, true);
|
||||
}
|
||||
|
||||
// 生成文件的最终名称
|
||||
String finalFileName = fileId + FILE_POSTFIX_SEPARATOR + fileSuffix;
|
||||
|
||||
// 存储文件
|
||||
byte[] bytes;
|
||||
try {
|
||||
bytes = file.getBytes();
|
||||
fileOperatorApi.storageFile(DEFAULT_BUCKET_NAME, finalFileName, bytes);
|
||||
} catch (IOException e) {
|
||||
String userTip = StrUtil.format(FileExceptionEnum.ERROR_FILE.getUserTip(), e.getMessage());
|
||||
throw new FileException(FileExceptionEnum.ERROR_FILE, userTip);
|
||||
}
|
||||
|
||||
// 计算文件大小kb
|
||||
long fileSizeKb = Convert.toLong(NumberUtil.div(new BigDecimal(file.getSize()), BigDecimal.valueOf(1024)).setScale(0, BigDecimal.ROUND_HALF_UP));
|
||||
|
||||
// 计算文件大小信息
|
||||
String fileSizeInfo = FileUtil.readableFileSize(file.getSize());
|
||||
|
||||
// 封装存储文件信息(上传替换公共信息)
|
||||
SysFileInfo sysFileInfo = new SysFileInfo();
|
||||
sysFileInfo.setFileLocation(FileLocationEnum.LOCAL.getCode());
|
||||
sysFileInfo.setFileBucket(DEFAULT_BUCKET_NAME);
|
||||
sysFileInfo.setFileObjectName(finalFileName);
|
||||
sysFileInfo.setFileOriginName(originalFilename);
|
||||
sysFileInfo.setFileSuffix(fileSuffix);
|
||||
sysFileInfo.setFileSizeKb(fileSizeKb);
|
||||
sysFileInfo.setFileSizeInfo(fileSizeInfo);
|
||||
sysFileInfo.setFileStatus(FileStatusEnum.NEW.getCode());
|
||||
sysFileInfo.setSecretFlag(sysFileInfoRequest.getSecretFlag());
|
||||
|
||||
// 返回结果
|
||||
return sysFileInfo;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,14 @@
|
|||
package cn.stylefeng.roses.kernel.file.modular.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import cn.stylefeng.roses.kernel.file.modular.entity.SysFileInfo;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.request.SysFileInfoRequest;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.response.SysFileInfoListResponse;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.response.SysFileInfoResponse;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -13,4 +20,50 @@ import cn.stylefeng.roses.kernel.file.modular.entity.SysFileInfo;
|
|||
*/
|
||||
public interface SysFileInfoMapper extends BaseMapper<SysFileInfo> {
|
||||
|
||||
/**
|
||||
* 根据附件IDS查询附件信息
|
||||
*
|
||||
* @param fileIdList 文件ID列表
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 12:57
|
||||
*/
|
||||
List<SysFileInfoResponse> getFileInfoListByFileIds(@Param("fileIdList") List<Long> fileIdList);
|
||||
|
||||
/**
|
||||
* 附件列表(有分页)
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 12:57
|
||||
*/
|
||||
List<SysFileInfoListResponse> fileInfoList(@Param("page") Page<SysFileInfoListResponse> page, @Param("sysFileInfoRequest") SysFileInfoRequest sysFileInfoRequest);
|
||||
|
||||
/**
|
||||
* 获取所有附件信息的code集合
|
||||
*
|
||||
* @param fileIdList 文件ID列表
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 12:57
|
||||
*/
|
||||
List<Long> getFileCodeByFileIds(@Param("fileIdList") List<Long> fileIdList);
|
||||
|
||||
/**
|
||||
* 修改fielCodes下所有附件状态
|
||||
*
|
||||
* @param fileCodeList 文件CODE列表
|
||||
* @param delFlag 是否删除
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 12:56
|
||||
*/
|
||||
void updateDelFlagByFileCodes(@Param("fileCodeList") List<Long> fileCodeList, @Param("delFlag") String delFlag);
|
||||
|
||||
/**
|
||||
* 修改fileIds下所有附件状态
|
||||
*
|
||||
* @param fileIdList 文件ID列表
|
||||
* @param delFlag 是否删除
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 12:56
|
||||
*/
|
||||
void updateDelFlagByFileIds(@Param("fileIdList") List<Long> fileIdList, @Param("delFlag") String delFlag);
|
||||
|
||||
}
|
||||
|
|
|
@ -2,4 +2,89 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.stylefeng.roses.kernel.file.modular.mapper.SysFileInfoMapper">
|
||||
|
||||
<!-- 根据附件IDS查询附件信息 -->
|
||||
<select id="getFileInfoListByFileIds"
|
||||
resultType="cn.stylefeng.roses.kernel.file.pojo.response.SysFileInfoResponse">
|
||||
SELECT file.file_id AS fileId,
|
||||
file.file_code AS fileCode,
|
||||
file.file_app_code AS fileAppCode,
|
||||
file.file_version AS fileVersion,
|
||||
file.file_status AS fileStatus,
|
||||
file.file_origin_name AS fileOriginName,
|
||||
file.file_suffix AS fileSuffix,
|
||||
file.file_size_kb AS fileSizeKb,
|
||||
file.file_size_info AS fileSizeInfo,
|
||||
file.secret_flag AS secretFlag,
|
||||
file.file_object_name AS fileObjectName,
|
||||
file.create_time AS createTime
|
||||
FROM sys_file_info file
|
||||
WHERE file.del_flag = "N"
|
||||
AND file.file_id IN
|
||||
<foreach collection="fileIdList" separator="," open="(" close=")" item="fileId">
|
||||
#{fileId}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<!-- 附件列表 -->
|
||||
<select id="fileInfoList" resultType="cn.stylefeng.roses.kernel.file.pojo.response.SysFileInfoListResponse">
|
||||
SELECT file.file_id AS fileId,
|
||||
file.file_app_code AS fileAppCode,
|
||||
app.app_name AS fileAppCodeName,
|
||||
file.file_origin_name AS fileOriginName,
|
||||
file.file_suffix AS fileSuffix,
|
||||
file.file_size_info AS fileSizeInfo,
|
||||
file.file_version AS fileVersion,
|
||||
file.create_account_id AS createAccountId,
|
||||
file.create_dept_id AS createDeptId,
|
||||
emp.emp_full_name_cn AS createUserName,
|
||||
file.create_time AS createTime,
|
||||
file.del_flag AS delFlag
|
||||
FROM sys_file_info file
|
||||
LEFT JOIN sys_app app ON file.file_app_code = app.app_code
|
||||
LEFT JOIN sys_account account ON account.account_id = file.create_account_id
|
||||
LEFT JOIN hr_emp_main emp ON account.emp_main_id = emp.emp_main_id
|
||||
<where>
|
||||
<if test="sysFileInfoRequest.fileAppCode != null and sysFileInfoRequest.fileAppCode != '' ">
|
||||
AND file.file_app_code = #{sysFileInfoRequest.fileAppCode}
|
||||
</if>
|
||||
<if test="sysFileInfoRequest.fileOriginName != null and sysFileInfoRequest.fileOriginName != '' ">
|
||||
AND file.file_app_code LIKE CONCAT('%',#{fileOriginName},'%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<!-- 获取所有附件信息的code集合 -->
|
||||
<select id="getFileCodeByFileIds" resultType="java.lang.Long">
|
||||
SELECT
|
||||
file.file_code
|
||||
FROM
|
||||
sys_file_info file
|
||||
WHERE
|
||||
file.file_id IN
|
||||
<foreach collection="fileIdList" open="(" close=")" separator="," item="fileId">
|
||||
#{fileId}
|
||||
</foreach>
|
||||
GROUP BY file.file_code
|
||||
</select>
|
||||
|
||||
<!-- 修改fileCodes下所有附件状态 -->
|
||||
<update id="updateDelFlagByFileCodes">
|
||||
UPDATE sys_file_info file
|
||||
SET file.del_flag = #{delFlag}
|
||||
WHERE file.file_code IN
|
||||
<foreach collection="fileCodeList" open="(" close=")" separator="," item="fileCode">
|
||||
#{fileCode}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<!-- 修改fileIds下所有附件状态 -->
|
||||
<update id="updateDelFlagByFileIds">
|
||||
UPDATE sys_file_info file
|
||||
SET file.del_flag = #{delFlag}
|
||||
WHERE file.file_id IN
|
||||
<foreach collection="fileIdList" open="(" close=")" separator="," item="fileId">
|
||||
#{fileId}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package cn.stylefeng.roses.kernel.file.modular.service;
|
||||
|
||||
import cn.stylefeng.roses.kernel.file.pojo.request.SysFileInfoRequest;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.response.SysFileInfoResponse;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
|
||||
import cn.stylefeng.roses.kernel.file.modular.entity.SysFileInfo;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.request.SysFileInfoRequest;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.response.SysFileInfoListResponse;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.response.SysFileInfoResponse;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -18,15 +19,36 @@ import java.util.List;
|
|||
*/
|
||||
public interface SysFileInfoService extends IService<SysFileInfo> {
|
||||
|
||||
/**
|
||||
* 获取文件信息结果集
|
||||
*
|
||||
* @param fileId 文件id
|
||||
* @return 文件信息结果集
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 14:16
|
||||
*/
|
||||
SysFileInfoResponse getFileInfoResult(Long fileId);
|
||||
|
||||
/**
|
||||
* 上传文件,返回文件的唯一标识
|
||||
*
|
||||
* @param file 要上传的文件
|
||||
* @return 文件id
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 13:38
|
||||
* @return 文件上传信息体
|
||||
* @author majianguo
|
||||
* @date 2020/12/16 15:47
|
||||
*/
|
||||
Long uploadFile(MultipartFile file);
|
||||
SysFileInfoResponse uploadFile(MultipartFile file, SysFileInfoRequest sysFileInfoRequest);
|
||||
|
||||
/**
|
||||
* 更新文件,返回文件的唯一标识
|
||||
*
|
||||
* @param file 要上传的文件
|
||||
* @param sysFileInfoRequest 如果是替换,需带上code以便版本升级
|
||||
* @return 文件上传返回体
|
||||
* @author majianguo
|
||||
* @date 2020/12/16 15:46
|
||||
*/
|
||||
SysFileInfoResponse updateFile(MultipartFile file, SysFileInfoRequest sysFileInfoRequest);
|
||||
|
||||
/**
|
||||
* 文件下载
|
||||
|
@ -39,23 +61,68 @@ public interface SysFileInfoService extends IService<SysFileInfo> {
|
|||
void download(SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 删除文件信息表
|
||||
* 删除文件信息(真删除文件信息)
|
||||
*
|
||||
* @param sysFileInfoRequest 删除参数
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 13:44
|
||||
*/
|
||||
void delete(SysFileInfoRequest sysFileInfoRequest);
|
||||
void deleteReally(SysFileInfoRequest sysFileInfoRequest);
|
||||
|
||||
/**
|
||||
* 文件预览,通过参数中传递文件id
|
||||
* 分页查询文件信息表
|
||||
*
|
||||
* @param sysFileInfoRequest 文件预览参数
|
||||
* @param response 响应结果
|
||||
* @param sysFileInfoRequest 查询参数
|
||||
* @return 查询分页结果
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 13:45
|
||||
* @date 2020/11/29 14:09
|
||||
*/
|
||||
void previewByFileId(SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response);
|
||||
PageResult<SysFileInfoListResponse> fileInfoListPage(SysFileInfoRequest sysFileInfoRequest);
|
||||
|
||||
/**
|
||||
* 打包下载文件
|
||||
*
|
||||
* @param fileIds 文件ID集合,使用,号分割
|
||||
* @param secretFlag 是否私有文件
|
||||
* @param response 响应结果
|
||||
* @author majianguo
|
||||
* @date 2020/12/7 下午4:47
|
||||
*/
|
||||
void packagingDownload(String fileIds, String secretFlag, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 根据附件IDS查询附件信息
|
||||
*
|
||||
* @param fileIds 附件IDS
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 12:52
|
||||
*/
|
||||
List<SysFileInfoResponse> getFileInfoListByFileIds(String fileIds);
|
||||
|
||||
/**
|
||||
* 文件预览
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 11:29
|
||||
*/
|
||||
void preview(SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 替换附件回调
|
||||
*
|
||||
* @param fileIdList 文件id列表
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 12:52
|
||||
*/
|
||||
void confirmReplaceFile(List<Long> fileIdList);
|
||||
|
||||
/**
|
||||
* 版本回退
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/12/27 13:49
|
||||
*/
|
||||
SysFileInfoResponse versionBack(SysFileInfoRequest sysFileInfoRequest);
|
||||
|
||||
/**
|
||||
* 文件预览,通过参数中传递fileBucket和fileObjectName
|
||||
|
@ -77,34 +144,4 @@ public interface SysFileInfoService extends IService<SysFileInfo> {
|
|||
*/
|
||||
SysFileInfo detail(SysFileInfoRequest sysFileInfoRequest);
|
||||
|
||||
/**
|
||||
* 分页查询文件信息表
|
||||
*
|
||||
* @param sysFileInfoRequest 查询参数
|
||||
* @return 查询分页结果
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 14:09
|
||||
*/
|
||||
PageResult<SysFileInfo> page(SysFileInfoRequest sysFileInfoRequest);
|
||||
|
||||
/**
|
||||
* 查询所有文件信息表
|
||||
*
|
||||
* @param sysFileInfoRequest 查询参数
|
||||
* @return 文件信息列表
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 14:15
|
||||
*/
|
||||
List<SysFileInfo> list(SysFileInfoRequest sysFileInfoRequest);
|
||||
|
||||
/**
|
||||
* 获取文件信息结果集
|
||||
*
|
||||
* @param fileId 文件id
|
||||
* @return 文件信息结果集
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 14:16
|
||||
*/
|
||||
SysFileInfoResponse getFileInfoResult(Long fileId);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package cn.stylefeng.roses.kernel.file.modular.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
|
||||
|
@ -10,15 +11,18 @@ import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
|
|||
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
|
||||
import cn.stylefeng.roses.kernel.file.FileInfoApi;
|
||||
import cn.stylefeng.roses.kernel.file.FileOperatorApi;
|
||||
import cn.stylefeng.roses.kernel.file.enums.FileLocationEnum;
|
||||
import cn.stylefeng.roses.kernel.file.enums.FileStatusEnum;
|
||||
import cn.stylefeng.roses.kernel.file.exception.FileException;
|
||||
import cn.stylefeng.roses.kernel.file.exception.enums.FileExceptionEnum;
|
||||
import cn.stylefeng.roses.kernel.file.modular.entity.SysFileInfo;
|
||||
import cn.stylefeng.roses.kernel.file.modular.factory.FileInfoFactory;
|
||||
import cn.stylefeng.roses.kernel.file.modular.mapper.SysFileInfoMapper;
|
||||
import cn.stylefeng.roses.kernel.file.modular.service.SysFileInfoService;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.request.SysFileInfoRequest;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.response.SysFileInfoListResponse;
|
||||
import cn.stylefeng.roses.kernel.file.pojo.response.SysFileInfoResponse;
|
||||
import cn.stylefeng.roses.kernel.file.util.DownloadUtil;
|
||||
import cn.stylefeng.roses.kernel.file.util.PdfFileTypeUtil;
|
||||
import cn.stylefeng.roses.kernel.file.util.PicFileTypeUtil;
|
||||
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
|
@ -27,18 +31,25 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static cn.stylefeng.roses.kernel.file.constants.FileConstants.DEFAULT_BUCKET_NAME;
|
||||
import static cn.stylefeng.roses.kernel.file.constants.FileConstants.FILE_POSTFIX_SEPARATOR;
|
||||
import static cn.stylefeng.roses.kernel.file.exception.enums.FileExceptionEnum.FILE_NOT_FOUND;
|
||||
|
||||
/**
|
||||
* 文件信息表 服务实现类
|
||||
|
@ -53,139 +64,9 @@ public class SysFileInfoServiceImpl extends ServiceImpl<SysFileInfoMapper, SysFi
|
|||
@Resource
|
||||
private FileOperatorApi fileOperatorApi;
|
||||
|
||||
@Override
|
||||
public Long uploadFile(MultipartFile file) {
|
||||
|
||||
// 生成文件的唯一id
|
||||
Long fileId = IdWorker.getId();
|
||||
|
||||
// 获取文件原始名称
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
|
||||
// 获取文件后缀,不包含点
|
||||
String fileSuffix = null;
|
||||
if (ObjectUtil.isNotEmpty(originalFilename)) {
|
||||
fileSuffix = StrUtil.subAfter(originalFilename, FILE_POSTFIX_SEPARATOR, true);
|
||||
}
|
||||
|
||||
// 生成文件的最终名称
|
||||
String finalFileName = fileId + FILE_POSTFIX_SEPARATOR + fileSuffix;
|
||||
|
||||
// 存储文件
|
||||
byte[] bytes;
|
||||
try {
|
||||
bytes = file.getBytes();
|
||||
fileOperatorApi.storageFile(DEFAULT_BUCKET_NAME, finalFileName, bytes);
|
||||
} catch (IOException e) {
|
||||
String userTip = StrUtil.format(FileExceptionEnum.ERROR_FILE.getUserTip(), e.getMessage());
|
||||
throw new FileException(FileExceptionEnum.ERROR_FILE, userTip);
|
||||
}
|
||||
|
||||
// 计算文件大小kb
|
||||
long fileSizeKb = Convert.toLong(NumberUtil.div(new BigDecimal(file.getSize()), BigDecimal.valueOf(1024))
|
||||
.setScale(0, BigDecimal.ROUND_HALF_UP));
|
||||
|
||||
// 存储文件信息
|
||||
SysFileInfo sysFileInfo = new SysFileInfo();
|
||||
sysFileInfo.setFileId(fileId);
|
||||
sysFileInfo.setFileLocation(FileLocationEnum.LOCAL.getCode());
|
||||
sysFileInfo.setFileBucket(DEFAULT_BUCKET_NAME);
|
||||
sysFileInfo.setFileObjectName(finalFileName);
|
||||
sysFileInfo.setFileOriginName(originalFilename);
|
||||
sysFileInfo.setFileSuffix(fileSuffix);
|
||||
sysFileInfo.setFileSizeKb(fileSizeKb);
|
||||
this.save(sysFileInfo);
|
||||
|
||||
// 返回文件id
|
||||
return fileId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
SysFileInfoResponse sysFileInfoResult = this.getFileInfoResult(sysFileInfoRequest.getFileId());
|
||||
String fileName = sysFileInfoResult.getFileOriginName();
|
||||
byte[] fileBytes = sysFileInfoResult.getFileBytes();
|
||||
DownloadUtil.download(fileName, fileBytes, response);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void delete(SysFileInfoRequest sysFileInfoRequest) {
|
||||
// 逻辑删除
|
||||
LambdaUpdateWrapper<SysFileInfo> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
|
||||
lambdaUpdateWrapper.set(SysFileInfo::getDelFlag, YesOrNotEnum.Y.getCode());
|
||||
lambdaUpdateWrapper.eq(SysFileInfo::getFileId, sysFileInfoRequest.getFileId());
|
||||
this.update(lambdaUpdateWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void previewByFileId(SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
|
||||
byte[] fileBytes;
|
||||
|
||||
// 根据文件id获取文件信息结果集
|
||||
SysFileInfoResponse sysFileInfoResult = this.getFileInfoResult(sysFileInfoRequest.getFileId());
|
||||
|
||||
// 获取文件后缀
|
||||
String fileSuffix = sysFileInfoResult.getFileSuffix().toLowerCase();
|
||||
|
||||
// 获取文件字节码
|
||||
fileBytes = sysFileInfoResult.getFileBytes();
|
||||
|
||||
// 如果是图片类型,则直接输出
|
||||
if (PicFileTypeUtil.getFileImgTypeFlag(fileSuffix)) {
|
||||
DownloadUtil.renderPreviewFile(response, fileBytes);
|
||||
} else {
|
||||
// 不支持别的文件预览
|
||||
throw new FileException(FileExceptionEnum.PREVIEW_ERROR_NOT_SUPPORT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void previewByBucketAndObjName(SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
|
||||
// 获取文件字节码
|
||||
byte[] fileBytes;
|
||||
try {
|
||||
fileBytes = fileOperatorApi.getFileBytes(sysFileInfoRequest.getFileBucket(), sysFileInfoRequest.getFileObjectName());
|
||||
} catch (Exception e) {
|
||||
log.error(">>> 获取文件流异常,具体信息为:{}", e.getMessage());
|
||||
throw new FileException(FileExceptionEnum.FILE_STREAM_ERROR);
|
||||
}
|
||||
|
||||
// 如果是图片类型,则直接输出
|
||||
if (PicFileTypeUtil.getFileImgTypeFlag(sysFileInfoRequest.getFileObjectName())) {
|
||||
DownloadUtil.renderPreviewFile(response, fileBytes);
|
||||
} else {
|
||||
// 不支持别的文件预览
|
||||
throw new FileException(FileExceptionEnum.PREVIEW_ERROR_NOT_SUPPORT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysFileInfo detail(SysFileInfoRequest sysFileInfoRequest) {
|
||||
return this.querySysFileInfo(sysFileInfoRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<SysFileInfo> page(SysFileInfoRequest sysFileInfoRequest) {
|
||||
LambdaQueryWrapper<SysFileInfo> queryWrapper = createWrapper(sysFileInfoRequest);
|
||||
Page<SysFileInfo> page = this.page(PageFactory.defaultPage(), queryWrapper);
|
||||
return PageResultFactory.createPageResult(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysFileInfo> list(SysFileInfoRequest sysFileInfoRequest) {
|
||||
LambdaQueryWrapper<SysFileInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysFileInfo::getDelFlag, YesOrNotEnum.N.getCode());
|
||||
return this.list(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysFileInfoResponse getFileInfoResult(Long fileId) {
|
||||
|
||||
SysFileInfoResponse sysFileInfoResult = new SysFileInfoResponse();
|
||||
|
||||
// 查询库中文件信息
|
||||
SysFileInfoRequest sysFileInfoRequest = new SysFileInfoRequest();
|
||||
sysFileInfoRequest.setFileId(fileId);
|
||||
|
@ -201,12 +82,257 @@ public class SysFileInfoServiceImpl extends ServiceImpl<SysFileInfoMapper, SysFi
|
|||
}
|
||||
|
||||
// 设置文件字节码
|
||||
SysFileInfoResponse sysFileInfoResult = new SysFileInfoResponse();
|
||||
BeanUtil.copyProperties(sysFileInfo, sysFileInfoResult);
|
||||
sysFileInfoResult.setFileBytes(fileBytes);
|
||||
|
||||
return sysFileInfoResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SysFileInfoResponse uploadFile(MultipartFile file, SysFileInfoRequest sysFileInfoRequest) {
|
||||
|
||||
// 文件请求转换存入数据库的附件信息
|
||||
SysFileInfo sysFileInfo = FileInfoFactory.createSysFileInfo(file, sysFileInfoRequest);
|
||||
|
||||
// 默认版本号从1开始
|
||||
sysFileInfo.setFileVersion(1);
|
||||
|
||||
// 文件编码生成
|
||||
sysFileInfo.setFileCode(IdWorker.getId());
|
||||
|
||||
// 保存附件到附件信息表
|
||||
this.save(sysFileInfo);
|
||||
|
||||
// 返回文件信息体
|
||||
SysFileInfoResponse fileUploadInfoResult = new SysFileInfoResponse();
|
||||
BeanUtil.copyProperties(sysFileInfo, fileUploadInfoResult);
|
||||
return fileUploadInfoResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysFileInfoResponse updateFile(MultipartFile file, SysFileInfoRequest sysFileInfoRequest) {
|
||||
|
||||
Long fileCode = sysFileInfoRequest.getFileCode();
|
||||
|
||||
// 转换存入数据库的附件信息
|
||||
SysFileInfo sysFileInfo = FileInfoFactory.createSysFileInfo(file, sysFileInfoRequest);
|
||||
sysFileInfo.setDelFlag(YesOrNotEnum.Y.getCode());
|
||||
sysFileInfo.setFileCode(fileCode);
|
||||
|
||||
// 查询该code下的最新版本号附件信息
|
||||
LambdaQueryWrapper<SysFileInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysFileInfo::getFileCode, fileCode);
|
||||
queryWrapper.eq(SysFileInfo::getDelFlag, YesOrNotEnum.N.getCode());
|
||||
queryWrapper.eq(SysFileInfo::getFileStatus, FileStatusEnum.NEW.getCode());
|
||||
SysFileInfo fileInfo = this.getOne(queryWrapper);
|
||||
if (ObjectUtil.isEmpty(fileInfo)) {
|
||||
throw new FileException(FileExceptionEnum.NOT_EXISTED);
|
||||
}
|
||||
|
||||
// 设置版本号在原本的基础上加一
|
||||
sysFileInfo.setFileVersion(fileInfo.getFileVersion() + 1);
|
||||
|
||||
// 存储新版本文件信息
|
||||
this.save(sysFileInfo);
|
||||
|
||||
// 返回文件信息体
|
||||
SysFileInfoResponse fileUploadInfoResult = new SysFileInfoResponse();
|
||||
BeanUtil.copyProperties(sysFileInfo, fileUploadInfoResult);
|
||||
return fileUploadInfoResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
|
||||
// 根据文件id获取文件信息结果集
|
||||
SysFileInfoResponse sysFileInfoResponse = this.getFileInfoResult(sysFileInfoRequest.getFileId());
|
||||
|
||||
// 如果文件加密等级不符合,文件不允许被访问
|
||||
if (!sysFileInfoRequest.getSecretFlag().equals(sysFileInfoResponse.getSecretFlag())) {
|
||||
throw new FileException(FileExceptionEnum.FILE_DENIED_ACCESS);
|
||||
}
|
||||
|
||||
DownloadUtil.download(sysFileInfoResponse.getFileOriginName(), sysFileInfoResponse.getFileBytes(), response);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void deleteReally(SysFileInfoRequest sysFileInfoRequest) {
|
||||
|
||||
// 查询该Code的所有历史版本
|
||||
LambdaQueryWrapper<SysFileInfo> lqw = new LambdaQueryWrapper<>();
|
||||
lqw.eq(SysFileInfo::getFileCode, sysFileInfoRequest.getFileCode());
|
||||
List<SysFileInfo> fileInfos = this.list(lqw);
|
||||
|
||||
// 批量删除
|
||||
this.removeByIds(fileInfos.stream().map(SysFileInfo::getFileId).collect(Collectors.toList()));
|
||||
|
||||
// 删除具体文件
|
||||
for (SysFileInfo fileInfo : fileInfos) {
|
||||
this.fileOperatorApi.deleteFile(fileInfo.getFileBucket(), fileInfo.getFileObjectName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<SysFileInfoListResponse> fileInfoListPage(SysFileInfoRequest sysFileInfoRequest) {
|
||||
Page<SysFileInfoListResponse> page = PageFactory.defaultPage();
|
||||
List<SysFileInfoListResponse> list = this.baseMapper.fileInfoList(page, sysFileInfoRequest);
|
||||
return PageResultFactory.createPageResult(page.setRecords(list));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packagingDownload(String fileIds, String secretFlag, HttpServletResponse response) {
|
||||
|
||||
// 获取文件信息
|
||||
List<Long> fileIdList = Arrays.stream(fileIds.split(",")).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
|
||||
List<SysFileInfoResponse> fileInfoResponseList = this.baseMapper.getFileInfoListByFileIds(fileIdList);
|
||||
|
||||
// 输出流等信息
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ZipOutputStream zip = new ZipOutputStream(bos);
|
||||
|
||||
try {
|
||||
for (int i = 0; i < fileInfoResponseList.size(); i++) {
|
||||
SysFileInfoResponse sysFileInfoResponse = fileInfoResponseList.get(i);
|
||||
if (ObjectUtil.isNotEmpty(sysFileInfoResponse)) {
|
||||
String fileOriginName = sysFileInfoResponse.getFileOriginName();
|
||||
// 判断公有文件下载时是否包含私有文件
|
||||
if (secretFlag.equals(YesOrNotEnum.N.getCode()) && !secretFlag.equals(sysFileInfoResponse.getSecretFlag())) {
|
||||
String userTip = StrUtil.format(FileExceptionEnum.SECRET_FLAG_INFO_ERROR.getUserTip(), fileOriginName);
|
||||
throw new FileException(FileExceptionEnum.SECRET_FLAG_INFO_ERROR, userTip);
|
||||
}
|
||||
|
||||
byte[] fileBytes = fileOperatorApi.getFileBytes(DEFAULT_BUCKET_NAME, sysFileInfoResponse.getFileObjectName());
|
||||
ZipEntry entry = new ZipEntry(i + 1 + "." + fileOriginName);
|
||||
entry.setSize(fileBytes.length);
|
||||
zip.putNextEntry(entry);
|
||||
zip.write(fileBytes);
|
||||
}
|
||||
}
|
||||
zip.finish();
|
||||
|
||||
// 下载文件
|
||||
DownloadUtil.download(DateUtil.now() + "-打包下载" + FILE_POSTFIX_SEPARATOR + "zip", bos.toByteArray(), response);
|
||||
} catch (Exception e) {
|
||||
log.error(">>> 获取文件流异常,具体信息为:{}", e.getMessage());
|
||||
throw new FileException(FileExceptionEnum.FILE_STREAM_ERROR);
|
||||
} finally {
|
||||
try {
|
||||
zip.closeEntry();
|
||||
zip.close();
|
||||
bos.close();
|
||||
} catch (IOException e) {
|
||||
log.error(">>> 关闭数据流失败,具体信息为:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysFileInfoResponse> getFileInfoListByFileIds(String fileIds) {
|
||||
List<Long> fileIdList = Arrays.stream(fileIds.split(",")).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
|
||||
return this.baseMapper.getFileInfoListByFileIds(fileIdList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preview(SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
|
||||
// 根据文件id获取文件信息结果集
|
||||
SysFileInfoResponse sysFileInfoResponse = this.getFileInfoResult(sysFileInfoRequest.getFileId());
|
||||
|
||||
// 如果文件加密等级不符合,文件不允许被访问
|
||||
if (!sysFileInfoRequest.getSecretFlag().equals(sysFileInfoResponse.getSecretFlag())) {
|
||||
throw new FileException(FileExceptionEnum.FILE_DENIED_ACCESS);
|
||||
}
|
||||
|
||||
// 获取文件后缀
|
||||
String fileSuffix = sysFileInfoResponse.getFileSuffix().toLowerCase();
|
||||
|
||||
// 获取文件字节码
|
||||
byte[] fileBytes = sysFileInfoResponse.getFileBytes();
|
||||
|
||||
// 附件预览
|
||||
this.renderPreviewFile(response, fileSuffix, fileBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void confirmReplaceFile(List<Long> fileIdList) {
|
||||
|
||||
// 获取所有附件信息的code集合
|
||||
if (fileIdList == null || fileIdList.size() == 0) {
|
||||
throw new FileException(FileExceptionEnum.FILE_IDS_EMPTY);
|
||||
}
|
||||
List<Long> fileCodeList = this.baseMapper.getFileCodeByFileIds(fileIdList);
|
||||
if (fileCodeList == null || fileCodeList.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 修改该codes下所有附件删除状态为Y
|
||||
this.baseMapper.updateDelFlagByFileCodes(fileCodeList, YesOrNotEnum.Y.getCode());
|
||||
|
||||
// 修改当前fileIds下所有附件删除状态为N
|
||||
this.baseMapper.updateDelFlagByFileIds(fileIdList, YesOrNotEnum.N.getCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SysFileInfoResponse versionBack(SysFileInfoRequest sysFileInfoRequest) {
|
||||
|
||||
LambdaQueryWrapper<SysFileInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysFileInfo::getFileId, sysFileInfoRequest.getFileId());
|
||||
SysFileInfo fileInfo = this.getOne(queryWrapper);
|
||||
|
||||
// 判断有没有这个文件
|
||||
if (ObjectUtil.isEmpty(fileInfo)) {
|
||||
String userTip = FileExceptionEnum.FILE_NOT_FOUND.getUserTip();
|
||||
String errorMessage = StrUtil.format(userTip, "文件:" + fileInfo.getFileId() + "未找到!");
|
||||
throw new FileException(FILE_NOT_FOUND.getErrorCode(), errorMessage);
|
||||
}
|
||||
|
||||
// 把之前的文件刷回
|
||||
LambdaUpdateWrapper<SysFileInfo> oldFileInfoLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
|
||||
oldFileInfoLambdaUpdateWrapper.eq(SysFileInfo::getFileCode, fileInfo.getFileCode());
|
||||
oldFileInfoLambdaUpdateWrapper.eq(SysFileInfo::getFileStatus, FileStatusEnum.NEW.getCode());
|
||||
oldFileInfoLambdaUpdateWrapper.set(SysFileInfo::getFileStatus, FileStatusEnum.OLD.getCode());
|
||||
this.update(oldFileInfoLambdaUpdateWrapper);
|
||||
|
||||
// 修改文件状态
|
||||
LambdaUpdateWrapper<SysFileInfo> newFileInfoLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
|
||||
newFileInfoLambdaUpdateWrapper.eq(SysFileInfo::getFileId, sysFileInfoRequest.getFileId());
|
||||
newFileInfoLambdaUpdateWrapper.set(SysFileInfo::getFileStatus, FileStatusEnum.NEW.getCode());
|
||||
newFileInfoLambdaUpdateWrapper.set(SysFileInfo::getDelFlag, YesOrNotEnum.N.getCode());
|
||||
this.update(newFileInfoLambdaUpdateWrapper);
|
||||
|
||||
// 返回
|
||||
return BeanUtil.toBean(fileInfo, SysFileInfoResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void previewByBucketAndObjName(SysFileInfoRequest sysFileInfoRequest, HttpServletResponse response) {
|
||||
|
||||
// 获取文件字节码
|
||||
byte[] fileBytes;
|
||||
try {
|
||||
fileBytes = fileOperatorApi.getFileBytes(sysFileInfoRequest.getFileBucket(), sysFileInfoRequest.getFileObjectName());
|
||||
} catch (Exception e) {
|
||||
log.error(">>> 获取文件流异常,具体信息为:{}", e.getMessage());
|
||||
throw new FileException(FileExceptionEnum.FILE_STREAM_ERROR);
|
||||
}
|
||||
|
||||
// 获取文件后缀
|
||||
String fileSuffix = FileUtil.getSuffix(sysFileInfoRequest.getFileObjectName());
|
||||
|
||||
// 附件预览
|
||||
this.renderPreviewFile(response, fileSuffix, fileBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysFileInfo detail(SysFileInfoRequest sysFileInfoRequest) {
|
||||
return this.querySysFileInfo(sysFileInfoRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysFileInfoResponse getFileInfoWithoutContent(Long fileId) {
|
||||
|
||||
|
@ -223,6 +349,39 @@ public class SysFileInfoServiceImpl extends ServiceImpl<SysFileInfoMapper, SysFi
|
|||
return sysFileInfoResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染被预览的文件到servlet的response流中
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/29 17:13
|
||||
*/
|
||||
private void renderPreviewFile(HttpServletResponse response, String fileSuffix, byte[] fileBytes) {
|
||||
|
||||
// 如果文件后缀是图片或者pdf,则直接输出流
|
||||
if (PicFileTypeUtil.getFileImgTypeFlag(fileSuffix) || PdfFileTypeUtil.getFilePdfTypeFlag(fileSuffix)) {
|
||||
try {
|
||||
// 设置contentType
|
||||
if (PicFileTypeUtil.getFileImgTypeFlag(fileSuffix)) {
|
||||
response.setContentType(MediaType.IMAGE_PNG_VALUE);
|
||||
} else if (PdfFileTypeUtil.getFilePdfTypeFlag(fileSuffix)) {
|
||||
response.setContentType(MediaType.APPLICATION_PDF_VALUE);
|
||||
}
|
||||
|
||||
// 获取outputStream
|
||||
ServletOutputStream outputStream = response.getOutputStream();
|
||||
|
||||
// 输出字节流
|
||||
IoUtil.write(outputStream, true, fileBytes);
|
||||
} catch (IOException e) {
|
||||
String userTip = StrUtil.format(FileExceptionEnum.WRITE_BYTES_ERROR.getUserTip(), e.getMessage());
|
||||
throw new FileException(FileExceptionEnum.WRITE_BYTES_ERROR, userTip);
|
||||
}
|
||||
} else {
|
||||
// 不支持别的文件预览
|
||||
throw new FileException(FileExceptionEnum.PREVIEW_ERROR_NOT_SUPPORT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件信息表
|
||||
*
|
||||
|
@ -238,41 +397,4 @@ public class SysFileInfoServiceImpl extends ServiceImpl<SysFileInfoMapper, SysFi
|
|||
return sysFileInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建组织架构的通用条件查询wrapper
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/11/6 10:16
|
||||
*/
|
||||
private LambdaQueryWrapper<SysFileInfo> createWrapper(SysFileInfoRequest sysFileInfoRequest) {
|
||||
LambdaQueryWrapper<SysFileInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (ObjectUtil.isNotNull(sysFileInfoRequest)) {
|
||||
|
||||
// 拼接文件存储位置条件
|
||||
if (ObjectUtil.isNotEmpty(sysFileInfoRequest.getFileLocation())) {
|
||||
queryWrapper.like(SysFileInfo::getFileLocation, sysFileInfoRequest.getFileLocation());
|
||||
}
|
||||
|
||||
// 拼接文件仓库条件
|
||||
if (ObjectUtil.isNotEmpty(sysFileInfoRequest.getFileBucket())) {
|
||||
queryWrapper.like(SysFileInfo::getFileBucket, sysFileInfoRequest.getFileBucket());
|
||||
}
|
||||
|
||||
// 拼接文件名称(上传时候的文件名)
|
||||
if (ObjectUtil.isNotEmpty(sysFileInfoRequest.getFileOriginName())) {
|
||||
queryWrapper.like(SysFileInfo::getFileOriginName, sysFileInfoRequest.getFileOriginName());
|
||||
}
|
||||
|
||||
// 拼接文件名称(存储到系统的文件名)
|
||||
if (ObjectUtil.isNotEmpty(sysFileInfoRequest.getFileObjectName())) {
|
||||
queryWrapper.like(SysFileInfo::getFileObjectName, sysFileInfoRequest.getFileObjectName());
|
||||
}
|
||||
}
|
||||
|
||||
// 查询没被删除的
|
||||
queryWrapper.eq(SysFileInfo::getDelFlag, YesOrNotEnum.N.getCode());
|
||||
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue