Compare commits

...

3 Commits

Author SHA1 Message Date
liuxiao
e56d001728 官网 分片上传、配置白名单 2024-07-10 13:54:07 +08:00
liuxiao
c051cc1d7b 官网 修改新闻详情 2024-07-10 09:55:04 +08:00
liuxiao
97a246dcc1 官网后台图片上传 2024-07-09 16:41:23 +08:00
35 changed files with 1686 additions and 132 deletions

View File

@ -10,6 +10,7 @@ import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.official.service.ISysImageService;
import com.ruoyi.system.domain.bo.SysOssBo;
import com.ruoyi.system.domain.vo.SysOssVo;
import com.ruoyi.system.service.ISysOssService;
@ -46,6 +47,7 @@ public class SysOssController extends BaseController {
private String filePath;
private final ISysOssService iSysOssService;
private final ISysImageService iSysImageService;
/**
* 查询OSS对象存储列表
@ -94,16 +96,15 @@ public class SysOssController extends BaseController {
* @param file 文件数据
* @return 文件上传地址信息
*/
@Log(title = "OSS对象存储", businessType = BusinessType.INSERT)
@Log(title = "本地文件上传", businessType = BusinessType.INSERT)
@PostMapping("/addPartsUpload")
public R<Map<String, String>> addPartsUpload(@RequestPart("file") MultipartFile file) {
Map<String,String> map=new HashMap<>();
log.info("上传的文件名称:{}",file.getOriginalFilename());
//文件上传的地址从配置文件中获取
log.info("上传的文件地址:{}",filePath);
String filePath=System.getProperty("user.dir")+"/file/upload/";
try {
if (file.isEmpty()) {
return R.fail("上传文件不能为空");
return R.warn("文件为空");
}
String fileName = System.currentTimeMillis()+"-"+file.getOriginalFilename();
@ -120,18 +121,15 @@ public class SysOssController extends BaseController {
file.transferTo(uploadFile);
String pathFan=filePath.replace("\\","/");
//filePath获取到的地址斜杠是 \ 单斜杠是特殊符号得用双斜杠代替得换成 / 才能访问到
map.put("url",filePath);
map.put("fileName",fileName);
log.info("替换后的文件名称:{}",pathFan+fileName);
SysOssVo sysOssVo = iSysOssService.uploadLocal(filePath, fileName);
map.put("ossId",sysOssVo.getOssId().toString());
//修改数据库
Long image = iSysImageService.uploadImage(fileName,pathFan+fileName);
System.err.println("替换后:"+pathFan);
map.put("url",pathFan+fileName);
map.put("fileName",fileName);
map.put("ossId",image.toString());
return R.ok(map);
} catch (IOException e) {
return R.fail("文件上传失败: "+e);
return R.warn("文件上传失败: "+e);
}
}

View File

@ -129,6 +129,8 @@ security:
- /**/*.html
- /**/*.css
- /**/*.js
- # 配置白名单
- /official/slideshow/**
# 公共路径
- /favicon.ico
- /error

View File

@ -0,0 +1,73 @@
package com.ruoyi.official.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.official.domain.bo.FileChunkFilelistBo;
import com.ruoyi.official.domain.bo.FileChunkParamBo;
import com.ruoyi.official.domain.vo.CheckSysChunkVo;
import com.ruoyi.official.domain.vo.FileChunkFilelistVo;
import com.ruoyi.official.service.IFileChunkFilelistService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
/**
* 已上传文件记录
*
* @author ruoyi
* @date 2024-07-10
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/official/chunkFilelist")
public class FileChunkFilelistController extends BaseController {
private final IFileChunkFilelistService iFileChunkFilelistService;
/**
* 查询已上传文件记录列表
*/
@SaCheckPermission("official:chunkFilelist:list")
@GetMapping("/list")
public TableDataInfo<FileChunkFilelistVo> list(FileChunkFilelistBo bo, PageQuery pageQuery) {
return iFileChunkFilelistService.queryPageList(bo, pageQuery);
}
/**
* 上传文件
* @param fileChunkParam 文件分片实体对象
* @param response 响应
* @return 是否上传成功
*/
@PostMapping("/upload")
public R<Void> postFileUpload(@ModelAttribute FileChunkParamBo fileChunkParam, HttpServletResponse response) {
return toAjax(iFileChunkFilelistService.postFileUpload(fileChunkParam, response));
}
/**
* 检查文件上传状态
*/
@GetMapping("/upload")
public R<CheckSysChunkVo> getFileUpload(@ModelAttribute FileChunkParamBo sysChunk, HttpServletResponse response) {
//查询根据md5查询文件是否存在
return R.ok(iFileChunkFilelistService.getFileUpload(sysChunk, response));
}
/**
* 合并请求
* @param filelistBo 已上传文件实体
* @return 合并是否成功
*/
@PostMapping("/merge")
public R<String> merge(FileChunkFilelistBo filelistBo) {
return R.ok("操作成功", iFileChunkFilelistService.mergeFile(filelistBo));
}
}

View File

@ -0,0 +1,108 @@
package com.ruoyi.official.controller;
import java.util.List;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.official.domain.vo.FileChunkParamVo;
import com.ruoyi.official.domain.bo.FileChunkParamBo;
import com.ruoyi.official.service.IFileChunkParamService;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 文件分片记录
*
* @author ruoyi
* @date 2024-07-10
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/official/chunkParam")
public class FileChunkParamController extends BaseController {
private final IFileChunkParamService iFileChunkParamService;
/**
* 查询文件分片记录列表
*/
@SaCheckPermission("official:chunkParam:list")
@GetMapping("/list")
public TableDataInfo<FileChunkParamVo> list(FileChunkParamBo bo, PageQuery pageQuery) {
return iFileChunkParamService.queryPageList(bo, pageQuery);
}
/**
* 导出文件分片记录列表
*/
@SaCheckPermission("official:chunkParam:export")
@Log(title = "文件分片记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(FileChunkParamBo bo, HttpServletResponse response) {
List<FileChunkParamVo> list = iFileChunkParamService.queryList(bo);
ExcelUtil.exportExcel(list, "文件分片记录", FileChunkParamVo.class, response);
}
/**
* 获取文件分片记录详细信息
*
* @param id 主键
*/
@SaCheckPermission("official:chunkParam:query")
@GetMapping("/{id}")
public R<FileChunkParamVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(iFileChunkParamService.queryById(id));
}
/**
* 新增文件分片记录
*/
@SaCheckPermission("official:chunkParam:add")
@Log(title = "文件分片记录", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody FileChunkParamBo bo) {
return toAjax(iFileChunkParamService.insertByBo(bo));
}
/**
* 修改文件分片记录
*/
@SaCheckPermission("official:chunkParam:edit")
@Log(title = "文件分片记录", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody FileChunkParamBo bo) {
return toAjax(iFileChunkParamService.updateByBo(bo));
}
/**
* 删除文件分片记录
*
* @param ids 主键串
*/
@SaCheckPermission("official:chunkParam:remove")
@Log(title = "文件分片记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(iFileChunkParamService.deleteWithValidByIds(Arrays.asList(ids), true));
}
}

View File

@ -41,10 +41,8 @@ public class GwLableController extends BaseController {
private final IGwLableService iGwLableService;
/**
* 查询标签封面信息
列表
* 查询标签封面信息列表
*/
@SaCheckPermission("official:lable:list")
@GetMapping("/list")
public TableDataInfo<GwLableVo> list(GwLableBo bo, PageQuery pageQuery) {
return iGwLableService.queryPageList(bo, pageQuery);

View File

@ -41,8 +41,7 @@ public class GwSlideshowController extends BaseController {
private final IGwSlideshowService iGwSlideshowService;
/**
* 查询新闻信息
列表
* 查询新闻信息列表
*/
@SaCheckPermission("official:slideshow:list")
@GetMapping("/list")
@ -67,7 +66,7 @@ public class GwSlideshowController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("official:slideshow:query")
/*@SaCheckPermission("official:slideshow:query")*/
@GetMapping("/{id}")
public R<GwSlideshowVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(iGwSlideshowService.queryById(id));

View File

@ -0,0 +1,59 @@
package com.ruoyi.official.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 已上传文件记录对象 file_chunk_filelist
*
* @author ruoyi
* @date 2024-07-10
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("file_chunk_filelist")
public class FileChunkFilelist extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "id")
private Long id;
/**
* 链接
*/
private String url;
/**
* 本地地址
*/
private String locationAddress;
/**
* 文件标识,MD5
*/
private String identifier;
/**
* 文件名
*/
private String filename;
/**
* 相对路径
*/
private String relativePath;
/**
* 创建者id
*/
private Long createUserId;
/**
* 更新者id
*/
private Long updateUserId;
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.official.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import com.ruoyi.common.core.domain.BaseEntity;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件分片记录对象 file_chunk_param
*
* @author ruoyi
* @date 2024-07-10
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("file_chunk_param")
public class FileChunkParam extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "id")
private Long id;
/**
* 文件块编号
*/
private Long chunkNumber;
/**
* 分块大小
*/
private Long chunkSize;
/**
* 当前分块大小
*/
private Long currentChunkSize;
/**
* 总块数
*/
private Long totalChunks;
/**
* 总大小
*/
private Long totalSize;
/**
* 文件标识,MD5
*/
private String identifier;
/**
* 文件名
*/
private String fileName;
/**
* 相对路径
*/
private String relativePath;
/**
* 创建者id
*/
private Long createUserId;
/**
* 更新者id
*/
private Long updateUserId;
/**
* 二进制文件
*/
@TableField(exist = false)
private MultipartFile file;
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.official.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 本地图片上传信息对象 sys_image
*
* @author liuxiao
* @date 2024-07-09
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_image")
public class SysImage extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 对象存储主键
*/
@TableId(value = "id")
private Long id;
/**
* 文件名
*/
private String fileName;
/**
* URL地址
*/
private String url;
}

View File

@ -0,0 +1,73 @@
package com.ruoyi.official.domain.bo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.util.Date;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 已上传文件记录业务对象 file_chunk_filelist
*
* @author ruoyi
* @date 2024-07-10
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class FileChunkFilelistBo extends BaseEntity {
/**
* 主键
*/
@NotNull(message = "主键不能为空", groups = { EditGroup.class })
private Long id;
/**
* 链接
*/
@NotBlank(message = "链接不能为空", groups = { AddGroup.class, EditGroup.class })
private String url;
/**
* 本地地址
*/
@NotBlank(message = "本地地址不能为空", groups = { AddGroup.class, EditGroup.class })
private String locationAddress;
/**
* 文件标识,MD5
*/
@NotBlank(message = "文件标识,MD5不能为空", groups = { AddGroup.class, EditGroup.class })
private String identifier;
/**
* 文件名
*/
@NotBlank(message = "文件名不能为空", groups = { AddGroup.class, EditGroup.class })
private String filename;
/**
* 相对路径
*/
@NotBlank(message = "相对路径不能为空", groups = { AddGroup.class, EditGroup.class })
private String relativePath;
/**
* 创建者id
*/
@NotNull(message = "创建者id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long createUserId;
/**
* 更新者id
*/
@NotNull(message = "更新者id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long updateUserId;
}

View File

@ -0,0 +1,81 @@
package com.ruoyi.official.domain.bo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.util.Date;
import com.ruoyi.common.core.domain.BaseEntity;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件分片记录业务对象 file_chunk_param
*
* @author ruoyi
* @date 2024-07-10
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class FileChunkParamBo extends BaseEntity {
/**
* 主键
*/
private Long id;
/**
* 文件块编号
*/
private Long chunkNumber;
/**
* 分块大小
*/
private Long chunkSize;
/**
* 当前分块大小
*/
private Long currentChunkSize;
/**
* 总块数
*/
private Long totalChunks;
/**
* 总大小
*/
private Long totalSize;
/**
* 文件标识,MD5
*/
private String identifier;
/**
* 文件名
*/
private String fileName;
/**
* 相对路径
*/
private String relativePath;
/**
* 二进制文件
*/
private MultipartFile file;
}

View File

@ -37,7 +37,6 @@ public class GwLableBo extends BaseEntity {
/**
* 文件类型 0图片 1视频
*/
@NotBlank(message = "文件类型 0图片 1视频不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileType;
/**
@ -49,7 +48,6 @@ public class GwLableBo extends BaseEntity {
/**
* 父菜单ID
*/
@NotNull(message = "父菜单ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long parentId;
/**
@ -67,7 +65,7 @@ public class GwLableBo extends BaseEntity {
/**
* 菜单类型M目录 C菜单
*/
@NotBlank(message = "菜单类型M目录 C菜单不能为空", groups = { AddGroup.class, EditGroup.class })
private String menuType;
/**
@ -79,13 +77,11 @@ public class GwLableBo extends BaseEntity {
/**
* 创建者id
*/
@NotNull(message = "创建者id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long createUserId;
/**
* 更新者id
*/
@NotNull(message = "更新者id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long updateUserId;

View File

@ -63,7 +63,6 @@ public class GwSlideshowBo extends BaseEntity {
/**
* 摘要
*/
@NotBlank(message = "摘要不能为空", groups = { AddGroup.class, EditGroup.class })
private String abstracts;
/**
@ -72,17 +71,4 @@ public class GwSlideshowBo extends BaseEntity {
@NotBlank(message = "是否置顶 0否 1是不能为空", groups = { AddGroup.class, EditGroup.class })
private String isTop;
/**
* 创建者id
*/
@NotNull(message = "创建者id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long createUserId;
/**
* 更新者id
*/
@NotNull(message = "更新者id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long updateUserId;
}

View File

@ -0,0 +1,43 @@
package com.ruoyi.official.domain.bo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.util.Date;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 本地图片上传信息业务对象 sys_image
*
* @author liuxiao
* @date 2024-07-09
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SysImageBo extends BaseEntity {
/**
* 对象存储主键
*/
@NotNull(message = "对象存储主键不能为空", groups = { EditGroup.class })
private Long id;
/**
* 文件名
*/
@NotBlank(message = "文件名不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileName;
/**
* URL地址
*/
@NotBlank(message = "URL地址不能为空", groups = { AddGroup.class, EditGroup.class })
private String url;
}

View File

@ -0,0 +1,23 @@
package com.ruoyi.official.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import lombok.Data;
import java.util.List;
/**
* @author: lx
* @since: 2024/7/10 11:12
* @description:
*/
@Data
public class CheckSysChunkVo {
private boolean skipUpload;
private List<Long> uploaded;
}

View File

@ -0,0 +1,73 @@
package com.ruoyi.official.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.convert.ExcelDictConvert;
import lombok.Data;
import java.util.Date;
/**
* 已上传文件记录视图对象 file_chunk_filelist
*
* @author ruoyi
* @date 2024-07-10
*/
@Data
@ExcelIgnoreUnannotated
public class FileChunkFilelistVo {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ExcelProperty(value = "主键")
private Long id;
/**
* 链接
*/
@ExcelProperty(value = "链接")
private String url;
/**
* 本地地址
*/
@ExcelProperty(value = "本地地址")
private String locationAddress;
/**
* 文件标识,MD5
*/
@ExcelProperty(value = "文件标识,MD5")
private String identifier;
/**
* 文件名
*/
@ExcelProperty(value = "文件名")
private String filename;
/**
* 相对路径
*/
@ExcelProperty(value = "相对路径")
private String relativePath;
/**
* 创建者id
*/
@ExcelProperty(value = "创建者id")
private Long createUserId;
/**
* 更新者id
*/
@ExcelProperty(value = "更新者id")
private Long updateUserId;
}

View File

@ -0,0 +1,91 @@
package com.ruoyi.official.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.convert.ExcelDictConvert;
import lombok.Data;
import java.util.Date;
/**
* 文件分片记录视图对象 file_chunk_param
*
* @author ruoyi
* @date 2024-07-10
*/
@Data
@ExcelIgnoreUnannotated
public class FileChunkParamVo {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ExcelProperty(value = "主键")
private Long id;
/**
* 文件块编号
*/
@ExcelProperty(value = "文件块编号")
private Long chunkNumber;
/**
* 分块大小
*/
@ExcelProperty(value = "分块大小")
private Long chunkSize;
/**
* 当前分块大小
*/
@ExcelProperty(value = "当前分块大小")
private Long currentChunkSize;
/**
* 总块数
*/
@ExcelProperty(value = "总块数")
private Long totalChunks;
/**
* 总大小
*/
@ExcelProperty(value = "总大小")
private Long totalSize;
/**
* 文件标识,MD5
*/
@ExcelProperty(value = "文件标识,MD5")
private String identifier;
/**
* 文件名
*/
@ExcelProperty(value = "文件名")
private String fileName;
/**
* 相对路径
*/
@ExcelProperty(value = "相对路径")
private String relativePath;
/**
* 创建者id
*/
@ExcelProperty(value = "创建者id")
private Long createUserId;
/**
* 更新者id
*/
@ExcelProperty(value = "更新者id")
private Long updateUserId;
}

View File

@ -0,0 +1,43 @@
package com.ruoyi.official.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.convert.ExcelDictConvert;
import lombok.Data;
import java.util.Date;
/**
* 本地图片上传信息视图对象 sys_image
*
* @author liuxiao
* @date 2024-07-09
*/
@Data
@ExcelIgnoreUnannotated
public class SysImageVo {
private static final long serialVersionUID = 1L;
/**
* 对象存储主键
*/
@ExcelProperty(value = "对象存储主键")
private Long id;
/**
* 文件名
*/
@ExcelProperty(value = "文件名")
private String fileName;
/**
* URL地址
*/
@ExcelProperty(value = "URL地址")
private String url;
}

View File

@ -0,0 +1,15 @@
package com.ruoyi.official.mapper;
import com.ruoyi.official.domain.FileChunkFilelist;
import com.ruoyi.official.domain.vo.FileChunkFilelistVo;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
/**
* 已上传文件记录Mapper接口
*
* @author ruoyi
* @date 2024-07-10
*/
public interface FileChunkFilelistMapper extends BaseMapperPlus<FileChunkFilelistMapper, FileChunkFilelist, FileChunkFilelistVo> {
}

View File

@ -0,0 +1,15 @@
package com.ruoyi.official.mapper;
import com.ruoyi.official.domain.FileChunkParam;
import com.ruoyi.official.domain.vo.FileChunkParamVo;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
/**
* 文件分片记录Mapper接口
*
* @author ruoyi
* @date 2024-07-10
*/
public interface FileChunkParamMapper extends BaseMapperPlus<FileChunkParamMapper, FileChunkParam, FileChunkParamVo> {
}

View File

@ -0,0 +1,15 @@
package com.ruoyi.official.mapper;
import com.ruoyi.official.domain.SysImage;
import com.ruoyi.official.domain.vo.SysImageVo;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
/**
* 本地图片上传信息Mapper接口
*
* @author liuxiao
* @date 2024-07-09
*/
public interface SysImageMapper extends BaseMapperPlus<SysImageMapper, SysImage, SysImageVo> {
}

View File

@ -0,0 +1,60 @@
package com.ruoyi.official.service;
import com.ruoyi.official.domain.FileChunkFilelist;
import com.ruoyi.official.domain.FileChunkParam;
import com.ruoyi.official.domain.bo.FileChunkParamBo;
import com.ruoyi.official.domain.vo.CheckSysChunkVo;
import com.ruoyi.official.domain.vo.FileChunkFilelistVo;
import com.ruoyi.official.domain.bo.FileChunkFilelistBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.List;
/**
* 已上传文件记录Service接口
*
* @author ruoyi
* @date 2024-07-10
*/
public interface IFileChunkFilelistService {
/**
* 查询已上传文件记录
*/
FileChunkFilelistVo queryById(Long id);
/**
* 查询已上传文件记录列表
*/
TableDataInfo<FileChunkFilelistVo> queryPageList(FileChunkFilelistBo bo, PageQuery pageQuery);
/**
* 查询已上传文件记录列表
*/
List<FileChunkFilelistVo> queryList(FileChunkFilelistBo bo);
/**
* 新增已上传文件记录
*/
Boolean insertByBo(FileChunkFilelistBo bo);
/**
* 修改已上传文件记录
*/
Boolean updateByBo(FileChunkFilelistBo bo);
/**
* 校验并批量删除已上传文件记录信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
boolean postFileUpload(FileChunkParamBo fileChunkParam, HttpServletResponse response);
CheckSysChunkVo getFileUpload(FileChunkParamBo fileChunkParam, HttpServletResponse response);
String mergeFile(FileChunkFilelistBo FileChunkFilelistBo);
}

View File

@ -0,0 +1,52 @@
package com.ruoyi.official.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.official.domain.FileChunkParam;
import com.ruoyi.official.domain.vo.FileChunkParamVo;
import com.ruoyi.official.domain.bo.FileChunkParamBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 文件分片记录Service接口
*
* @author ruoyi
* @date 2024-07-10
*/
public interface IFileChunkParamService {
/**
* 查询文件分片记录
*/
FileChunkParamVo queryById(Long id);
/**
* 查询文件分片记录列表
*/
TableDataInfo<FileChunkParamVo> queryPageList(FileChunkParamBo bo, PageQuery pageQuery);
/**
* 查询文件分片记录列表
*/
List<FileChunkParamVo> queryList(FileChunkParamBo bo);
/**
* 新增文件分片记录
*/
Boolean insertByBo(FileChunkParamBo bo);
/**
* 修改文件分片记录
*/
Boolean updateByBo(FileChunkParamBo bo);
/**
* 校验并批量删除文件分片记录信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
void remove(LambdaQueryWrapper<FileChunkParam> wrapper);
}

View File

@ -0,0 +1,53 @@
package com.ruoyi.official.service;
import com.ruoyi.official.domain.SysImage;
import com.ruoyi.official.domain.vo.SysImageVo;
import com.ruoyi.official.domain.bo.SysImageBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 本地图片上传信息Service接口
*
* @author liuxiao
* @date 2024-07-09
*/
public interface ISysImageService {
/**
* 查询本地图片上传信息
*/
SysImageVo queryById(Long id);
/**
* 查询本地图片上传信息列表
*/
TableDataInfo<SysImageVo> queryPageList(SysImageBo bo, PageQuery pageQuery);
/**
* 查询本地图片上传信息列表
*/
List<SysImageVo> queryList(SysImageBo bo);
/**
* 新增本地图片上传信息
*/
Boolean insertByBo(SysImageBo bo);
/**
* 修改本地图片上传信息
*/
Boolean updateByBo(SysImageBo bo);
Long uploadImage(String fileName,String url);
/**
* 校验并批量删除本地图片上传信息信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,318 @@
package com.ruoyi.official.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.official.domain.FileChunkParam;
import com.ruoyi.official.domain.bo.FileChunkParamBo;
import com.ruoyi.official.domain.vo.CheckSysChunkVo;
import com.ruoyi.official.domain.vo.FileChunkParamVo;
import com.ruoyi.official.mapper.FileChunkParamMapper;
import com.ruoyi.official.service.IFileChunkParamService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.official.domain.bo.FileChunkFilelistBo;
import com.ruoyi.official.domain.vo.FileChunkFilelistVo;
import com.ruoyi.official.domain.FileChunkFilelist;
import com.ruoyi.official.mapper.FileChunkFilelistMapper;
import com.ruoyi.official.service.IFileChunkFilelistService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.Security;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;
/**
* 已上传文件记录Service业务层处理
*
* @author ruoyi
* @date 2024-07-10
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class FileChunkFilelistServiceImpl implements IFileChunkFilelistService {
private final FileChunkFilelistMapper baseMapper;
private final FileChunkParamMapper fileChunkParamMapper;
private final IFileChunkParamService iFileChunkParamService;
@Value("${ruoyi.profile}")
private String filePath;
private final static String folderPath = "/file";
/**
* 查询已上传文件记录
*/
@Override
public FileChunkFilelistVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 查询已上传文件记录列表
*/
@Override
public TableDataInfo<FileChunkFilelistVo> queryPageList(FileChunkFilelistBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<FileChunkFilelist> lqw = buildQueryWrapper(bo);
Page<FileChunkFilelistVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询已上传文件记录列表
*/
@Override
public List<FileChunkFilelistVo> queryList(FileChunkFilelistBo bo) {
LambdaQueryWrapper<FileChunkFilelist> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<FileChunkFilelist> buildQueryWrapper(FileChunkFilelistBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<FileChunkFilelist> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getUrl()), FileChunkFilelist::getUrl, bo.getUrl());
lqw.eq(StringUtils.isNotBlank(bo.getLocationAddress()), FileChunkFilelist::getLocationAddress, bo.getLocationAddress());
lqw.eq(StringUtils.isNotBlank(bo.getIdentifier()), FileChunkFilelist::getIdentifier, bo.getIdentifier());
lqw.like(StringUtils.isNotBlank(bo.getFilename()), FileChunkFilelist::getFilename, bo.getFilename());
lqw.eq(StringUtils.isNotBlank(bo.getRelativePath()), FileChunkFilelist::getRelativePath, bo.getRelativePath());
lqw.eq(bo.getCreateUserId() != null, FileChunkFilelist::getCreateUserId, bo.getCreateUserId());
lqw.eq(bo.getUpdateUserId() != null, FileChunkFilelist::getUpdateUserId, bo.getUpdateUserId());
return lqw;
}
/**
* 新增已上传文件记录
*/
@Override
public Boolean insertByBo(FileChunkFilelistBo bo) {
FileChunkFilelist add = BeanUtil.toBean(bo, FileChunkFilelist.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改已上传文件记录
*/
@Override
public Boolean updateByBo(FileChunkFilelistBo bo) {
FileChunkFilelist update = BeanUtil.toBean(bo, FileChunkFilelist.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(FileChunkFilelist entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除已上传文件记录
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
/**
* 每一个上传块都会包含如下分块信息
* chunkNumber: 当前块的次序第一个块是 1注意不是从 0 开始的
* totalChunks: 文件被分成块的总数
* chunkSize: 分块大小根据 totalSize 和这个值你就可以计算出总共的块数注意最后一块的大小可能会比这个要大
* currentChunkSize: 当前块的大小实际大小
* totalSize: 文件总大小
* identifier: 这个就是每个文件的唯一标示,md5码
* fileName: 文件名
* relativePath: 文件夹上传的时候文件的相对路径属性
* 一个分块可以被上传多次当然这肯定不是标准行为这种重传也但是在实际上传过程中是可能发生这种事情的是本库的特性之一
*/
@Override
@Transactional(rollbackFor = Exception.class)
public boolean postFileUpload(FileChunkParamBo fileChunkParam, HttpServletResponse response) {
MultipartFile file = fileChunkParam.getFile();
log.debug("file originName: {}, chunkNumber: {}", file.getOriginalFilename(), fileChunkParam.getChunkNumber());
Path path = Paths.get(generatePath(filePath + folderPath, fileChunkParam));
try {
Files.write(path, fileChunkParam.getFile().getBytes());
log.debug("文件 {} 写入成功, md5:{}", fileChunkParam.getFileName(), fileChunkParam.getIdentifier());
return iFileChunkParamService.insertByBo(fileChunkParam);
//写入数据库
} catch (IOException e) {
throw new RuntimeException("上传失败" + e.getMessage());
}
}
@Override
public CheckSysChunkVo getFileUpload(FileChunkParamBo fileChunkParam, HttpServletResponse response) {
// 检查该文件是否存在于fileList中吗,直接返回skipUpload为true,执行闪传
//fileChunkParamMapper
String identifier = fileChunkParam.getIdentifier();
// 检查该文件是否存在于fileList中吗,直接返回skipUpload为true,执行闪传
CheckSysChunkVo checkSysChunkVo = new CheckSysChunkVo();
// 先查询文件分片管理表和已上传文件记录表
// List<SysChunk> sysChunkList = fileChunkParamMapper.list(new LambdaQueryWrapper<SysChunk>().eq(SysChunk::getIdentifier, identifier));
List<FileChunkParamVo> sysChunkList = fileChunkParamMapper.selectVoList(Wrappers.<FileChunkParam>lambdaQuery().eq(FileChunkParam::getIdentifier, identifier));
List<FileChunkFilelistVo> sysFilelistList = baseMapper.selectVoList(Wrappers.<FileChunkFilelist>lambdaQuery().eq(FileChunkFilelist::getIdentifier, identifier));
// 检查文件中是否存在于sysFilelistList中
if (sysFilelistList != null && !sysFilelistList.isEmpty()) {
checkSysChunkVo.setSkipUpload(true);
return checkSysChunkVo;
}
// 获取已存在的块的chunkNumber列表并返回给前端
if (sysChunkList != null && !sysChunkList.isEmpty()) {
List<Long> uploadedChunks = sysChunkList.stream()
.map(FileChunkParamVo::getChunkNumber)
.collect(Collectors.toList());
checkSysChunkVo.setUploaded(uploadedChunks);
}
return checkSysChunkVo;
}
/**
* 合并请求
* @param sysFilelist 已上传文件实体
* @return 合并是否成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public String mergeFile(FileChunkFilelistBo sysFilelist) {
// 获取文件的名称
String fileName = sysFilelist.getFilename();
String file = filePath + folderPath + "/" + sysFilelist.getIdentifier() + "/" + fileName;
String folder = filePath + folderPath + "/" + sysFilelist.getIdentifier();
String url = folderPath + "/" + sysFilelist.getIdentifier() + "/" + fileName;
merge(file, folder, fileName);
//当前文件已存在数据库中时,返回已存在标识
Long selectCount = baseMapper.selectCount(new LambdaQueryWrapper<FileChunkFilelist>()
.eq(FileChunkFilelist::getFilename, sysFilelist.getFilename())
.eq(FileChunkFilelist::getIdentifier, sysFilelist.getIdentifier()));
if (selectCount > 0) {
return url;
}
sysFilelist.setLocationAddress(file);
sysFilelist.setUrl(url);
sysFilelist.setCreateTime(new Date());
Boolean flag = insertByBo(sysFilelist);
if (flag) {
// 插入文件记录成功后,删除chunk表中的对应记录,释放空间
LambdaQueryWrapper<FileChunkParam> chunkLambdaQueryWrapper = new LambdaQueryWrapper<FileChunkParam>()
.eq(FileChunkParam::getFileName, sysFilelist.getFilename())
.eq(FileChunkParam::getIdentifier, sysFilelist.getIdentifier());
iFileChunkParamService.remove(chunkLambdaQueryWrapper);
}
return url;
}
/**
* 生成块文件所在地址
*/
private String generatePath(String uploadFolder, FileChunkParamBo fileChunkParam) {
StringBuilder stringBuilder = new StringBuilder();
// 文件夹地址md5
stringBuilder.append(uploadFolder).append("/").append(fileChunkParam.getIdentifier());
//判断uploadFolder/identifier 路径是否存在不存在则创建
if (!Files.isWritable(Paths.get(stringBuilder.toString()))) {
log.info("path not exist,create path: {}", stringBuilder.toString());
try {
Files.createDirectories(Paths.get(stringBuilder.toString()));
} catch (IOException e) {
log.error("生成时出现问题" + e.getMessage(), e);
throw new RuntimeException("生成时出现问题" + e.getMessage());
}
}
//文件夹地址/md5/文件名-1
return stringBuilder.append("/")
.append(fileChunkParam.getFileName())
.append("-")
.append(fileChunkParam.getChunkNumber()).toString();
}
/**
* 文件合并
*
* @param targetFile 要形成的文件名
* @param folder 要形成的文件夹地址
* @param fileName 文件的名称
*/
public static void merge(String targetFile, String folder, String fileName) {
try {
// 创建目标文件
Files.createFile(Paths.get(targetFile));
// 收集需要合并的文件路径并排序
List<Path> filesToMerge = Files.list(Paths.get(folder))
.filter(path -> !path.getFileName().toString().equals(fileName))
.sorted((o1, o2) -> {
String p1 = o1.getFileName().toString();
String p2 = o2.getFileName().toString();
int i1 = p1.lastIndexOf("-");
int i2 = p2.lastIndexOf("-");
return Integer.valueOf(p2.substring(i2)).compareTo(Integer.valueOf(p1.substring(i1)));
})
.collect(Collectors.toList());
// 注释掉的逻辑中 是以追加的形式写入文件 这样做在传送大文件时会出现合并失败的情况
// 我的推断可能是因为每次循环迭代中都会执行文件的读取和写入操作这种方式对于大文件来说效率不高并且可能会导致内存不足或者文件操作异常
// 所以这里使用缓冲流逐个合并文件, 不一次性读取整个文件内容而是使用缓冲区逐段读取和写入以降低内存使用量
try (OutputStream out = Files.newOutputStream(Paths.get(targetFile), StandardOpenOption.APPEND)) {
for (Path path : filesToMerge) {
try (InputStream in = Files.newInputStream(path)) {
byte[] buffer = new byte[8192]; // 8KB缓冲区
int len;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
}
// 合并后删除该块
Files.delete(path);
}
}
} catch (IOException e) {
log.error("合并出现错误:" + e.getMessage(), e);
throw new RuntimeException("合并出现错误," + e.getMessage());
}
}
}

View File

@ -0,0 +1,121 @@
package com.ruoyi.official.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.official.domain.bo.FileChunkParamBo;
import com.ruoyi.official.domain.vo.FileChunkParamVo;
import com.ruoyi.official.domain.FileChunkParam;
import com.ruoyi.official.mapper.FileChunkParamMapper;
import com.ruoyi.official.service.IFileChunkParamService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 文件分片记录Service业务层处理
*
* @author ruoyi
* @date 2024-07-10
*/
@RequiredArgsConstructor
@Service
public class FileChunkParamServiceImpl implements IFileChunkParamService {
private final FileChunkParamMapper baseMapper;
/**
* 查询文件分片记录
*/
@Override
public FileChunkParamVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 查询文件分片记录列表
*/
@Override
public TableDataInfo<FileChunkParamVo> queryPageList(FileChunkParamBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<FileChunkParam> lqw = buildQueryWrapper(bo);
Page<FileChunkParamVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询文件分片记录列表
*/
@Override
public List<FileChunkParamVo> queryList(FileChunkParamBo bo) {
LambdaQueryWrapper<FileChunkParam> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<FileChunkParam> buildQueryWrapper(FileChunkParamBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<FileChunkParam> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getChunkNumber() != null, FileChunkParam::getChunkNumber, bo.getChunkNumber());
lqw.eq(bo.getChunkSize() != null, FileChunkParam::getChunkSize, bo.getChunkSize());
lqw.eq(bo.getCurrentChunkSize() != null, FileChunkParam::getCurrentChunkSize, bo.getCurrentChunkSize());
lqw.eq(bo.getTotalChunks() != null, FileChunkParam::getTotalChunks, bo.getTotalChunks());
lqw.eq(bo.getTotalSize() != null, FileChunkParam::getTotalSize, bo.getTotalSize());
lqw.eq(StringUtils.isNotBlank(bo.getIdentifier()), FileChunkParam::getIdentifier, bo.getIdentifier());
lqw.like(StringUtils.isNotBlank(bo.getFileName()), FileChunkParam::getFileName, bo.getFileName());
lqw.eq(StringUtils.isNotBlank(bo.getRelativePath()), FileChunkParam::getRelativePath, bo.getRelativePath());
return lqw;
}
/**
* 新增文件分片记录
*/
@Override
public Boolean insertByBo(FileChunkParamBo bo) {
FileChunkParam add = BeanUtil.toBean(bo, FileChunkParam.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改文件分片记录
*/
@Override
public Boolean updateByBo(FileChunkParamBo bo) {
FileChunkParam update = BeanUtil.toBean(bo, FileChunkParam.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(FileChunkParam entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除文件分片记录
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public void remove(LambdaQueryWrapper<FileChunkParam> wrapper) {
baseMapper.delete(wrapper);
}
}

View File

@ -17,16 +17,13 @@ import com.ruoyi.official.domain.GwSlideshow;
import com.ruoyi.official.mapper.GwSlideshowMapper;
import com.ruoyi.official.service.IGwSlideshowService;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
* 新闻信息
Service业务层处理
* Service业务层处理
*
* @author ruoyi
* @date 2024-06-19
@ -39,25 +36,29 @@ public class GwSlideshowServiceImpl implements IGwSlideshowService {
/**
* 查询新闻信息
*/
@Override
public GwSlideshowVo queryById(Long id){
public GwSlideshowVo queryById(Long id) {
GwSlideshowVo gwSlideshowVo = baseMapper.selectVoById(id);
//查询详情时返回上一篇下一篇处理
List<GwSlideshow> list = baseMapper.selectList(Wrappers.<GwSlideshow>lambdaQuery().orderByDesc(GwSlideshow::getCreateTime));
getPrevNextArticles(id, gwSlideshowVo, list);
return gwSlideshowVo;
}
private Map<String, Object> getPrevNextArticles(Long id, GwSlideshowVo gwSlideshowVo, List<GwSlideshow> list) {
Map<String, Object> hashMap = new HashMap<>(16);
if(CollUtil.isNotEmpty(list)){
List<Long> collect = list.stream().map(GwSlideshow::getId).collect(Collectors.toList());
if (collect.contains(id)){
int currentSubscript = collect.indexOf(id);
hashMap.put("previous",list.get(currentSubscript-1));
hashMap.put("nextArticle",list.get(currentSubscript+1));
gwSlideshowVo.setSlideshowMap(hashMap);
}
if (CollUtil.isEmpty(list)) return hashMap;
Optional<GwSlideshow> first = list.stream().filter(itx -> Objects.equals(itx.getId(), id)).findFirst();
if (first.isPresent()) {
int index = list.indexOf(first.get());
if (index > 0) hashMap.put("previous", list.get(index - 1));
if (index < list.size() - 1) hashMap.put("nextArticle", list.get(index + 1));
}
return gwSlideshowVo;
gwSlideshowVo.setSlideshowMap(hashMap);
return hashMap;
}
/**
@ -89,15 +90,12 @@ public class GwSlideshowServiceImpl implements IGwSlideshowService {
lqw.eq(StringUtils.isNotBlank(bo.getNewsContent()), GwSlideshow::getNewsContent, bo.getNewsContent());
lqw.eq(StringUtils.isNotBlank(bo.getAbstracts()), GwSlideshow::getAbstracts, bo.getAbstracts());
lqw.eq(StringUtils.isNotBlank(bo.getIsTop()), GwSlideshow::getIsTop, bo.getIsTop());
lqw.eq(bo.getCreateUserId() != null, GwSlideshow::getCreateUserId, bo.getCreateUserId());
lqw.eq(bo.getUpdateUserId() != null, GwSlideshow::getUpdateUserId, bo.getUpdateUserId());
lqw.orderByDesc(GwSlideshow::getCreateTime);
return lqw;
}
/**
* 新增新闻信息
*/
@Override
public Boolean insertByBo(GwSlideshowBo bo) {
@ -112,7 +110,6 @@ public class GwSlideshowServiceImpl implements IGwSlideshowService {
/**
* 修改新闻信息
*/
@Override
public Boolean updateByBo(GwSlideshowBo bo) {
@ -124,28 +121,27 @@ public class GwSlideshowServiceImpl implements IGwSlideshowService {
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(GwSlideshow entity){
private void validEntityBeforeSave(GwSlideshow entity) {
//TODO 做一些数据校验,如唯一约束
//存在已置顶的数据不允许添加编辑
if (ObjectUtil.isNotEmpty(entity.getId())){
if (ObjectUtil.isNotEmpty(entity.getId())) {
//编辑
boolean exists = baseMapper.exists(Wrappers.<GwSlideshow>lambdaQuery().eq(GwSlideshow::getIsTop, "1"));
if (exists)throw new RuntimeException("已存在置顶的图片信息!");
}else {
if (exists && entity.getIsTop().equals("1")) throw new RuntimeException("已存在置顶的图片信息!");
} else {
//新增
boolean exists = baseMapper.exists(Wrappers.<GwSlideshow>lambdaQuery().eq(GwSlideshow::getIsTop, "1"));
if (exists)throw new RuntimeException("已存在置顶的图片信息!");
if (exists && entity.getIsTop().equals("1")) throw new RuntimeException("已存在置顶的图片信息!");
}
}
/**
* 批量删除新闻信息
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;

View File

@ -0,0 +1,121 @@
package com.ruoyi.official.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.official.domain.bo.SysImageBo;
import com.ruoyi.official.domain.vo.SysImageVo;
import com.ruoyi.official.domain.SysImage;
import com.ruoyi.official.mapper.SysImageMapper;
import com.ruoyi.official.service.ISysImageService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 本地图片上传信息Service业务层处理
*
* @author liuxiao
* @date 2024-07-09
*/
@RequiredArgsConstructor
@Service
public class SysImageServiceImpl implements ISysImageService {
private final SysImageMapper baseMapper;
/**
* 查询本地图片上传信息
*/
@Override
public SysImageVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 查询本地图片上传信息列表
*/
@Override
public TableDataInfo<SysImageVo> queryPageList(SysImageBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<SysImage> lqw = buildQueryWrapper(bo);
Page<SysImageVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询本地图片上传信息列表
*/
@Override
public List<SysImageVo> queryList(SysImageBo bo) {
LambdaQueryWrapper<SysImage> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<SysImage> buildQueryWrapper(SysImageBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<SysImage> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getFileName()), SysImage::getFileName, bo.getFileName());
lqw.eq(StringUtils.isNotBlank(bo.getUrl()), SysImage::getUrl, bo.getUrl());
return lqw;
}
/**
* 新增本地图片上传信息
*/
@Override
public Boolean insertByBo(SysImageBo bo) {
SysImage add = BeanUtil.toBean(bo, SysImage.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改本地图片上传信息
*/
@Override
public Boolean updateByBo(SysImageBo bo) {
SysImage update = BeanUtil.toBean(bo, SysImage.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
@Override
public Long uploadImage(String fileName,String url) {
SysImageVo sysImageVo = baseMapper.selectVoOne(Wrappers.<SysImage>lambdaQuery().eq(SysImage::getFileName, fileName));
if (ObjectUtil.isNotEmpty(sysImageVo)) throw new RuntimeException("图片已存在,请勿重复添加!");
SysImage sysImage = new SysImage();
sysImage.setFileName(fileName);
sysImage.setUrl(url);
return baseMapper.insert(sysImage) > 0 ? sysImage.getId() : null;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(SysImage entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除本地图片上传信息
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@ -1,6 +1,7 @@
package com.ruoyi.system.domain.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
@ -10,6 +11,7 @@ import java.util.Date;
* @author Lion Li
*/
@Data
@Accessors(chain = true) //开启链式编程,setter方法返回的是this也就是对象自己代替了默认的返回值void
public class SysOssVo {
private static final long serialVersionUID = 1L;

View File

@ -1,6 +1,7 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
@ -60,13 +61,12 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
@Override
public List<SysOssVo> listByIds(Collection<Long> ossIds) {
List<SysOssVo> list = new ArrayList<>();
for (Long id : ossIds) {
SysOssVo vo = SpringUtils.getAopProxy(this).getById(id);
if (ObjectUtil.isNotNull(vo)) {
list.add(this.matchingUrl(vo));
}
}
return list;
Optional<Long> first = ossIds.stream().findFirst();
List<SysOssVo> sysOssVos = baseMapper.selectVoList(Wrappers.<SysOss>lambdaQuery().eq(SysOss::getOssId, first.get()));
return CollUtil.isNotEmpty(sysOssVos)?sysOssVos.stream().map(itx->{
System.out.println(itx.getUrl()+"/"+itx.getFileName());
return itx.setUrl(itx.getUrl()+"/"+itx.getFileName());
}).collect(Collectors.toList()):null;
}
@Override
@ -110,7 +110,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
OssClient storage = OssFactory.instance();
try(InputStream inputStream = storage.getObjectContent(sysOss.getUrl())) {
try (InputStream inputStream = storage.getObjectContent(sysOss.getUrl())) {
int available = inputStream.available();
IoUtil.copy(inputStream, response.getOutputStream(), available);
response.setContentLength(available);
@ -144,13 +144,13 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
}
@Override
public SysOssVo uploadLocal(String imageUrl,String fileName) {
public SysOssVo uploadLocal(String imageUrl, String fileName) {
// 保存文件信息
SysOss oss = new SysOss();
oss.setUrl(imageUrl);
oss.setFileName(fileName);
baseMapper.insert(oss);
return BeanUtil.toBean(oss,SysOssVo.class);
return BeanUtil.toBean(oss, SysOssVo.class);
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.official.mapper.FileChunkFilelistMapper">
<resultMap type="com.ruoyi.official.domain.FileChunkFilelist" id="FileChunkFilelistResult">
<result property="id" column="id"/>
<result property="url" column="url"/>
<result property="locationAddress" column="locationAddress"/>
<result property="identifier" column="identifier"/>
<result property="filename" column="filename"/>
<result property="relativePath" column="relative_path"/>
<result property="createBy" column="create_by"/>
<result property="createUserId" column="create_user_id"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateUserId" column="update_user_id"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.official.mapper.FileChunkParamMapper">
<resultMap type="com.ruoyi.official.domain.FileChunkParam" id="FileChunkParamResult">
<result property="id" column="id"/>
<result property="chunkNumber" column="chunk_number"/>
<result property="chunkSize" column="chunk_size"/>
<result property="currentChunkSize" column="current_chunk_size"/>
<result property="totalChunks" column="total_chunks"/>
<result property="totalSize" column="total_size"/>
<result property="identifier" column="identifier"/>
<result property="filename" column="filename"/>
<result property="relativePath" column="relative_path"/>
<result property="createBy" column="create_by"/>
<result property="createUserId" column="create_user_id"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateUserId" column="update_user_id"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.official.mapper.SysImageMapper">
<resultMap type="com.ruoyi.official.domain.SysImage" id="SysImageResult">
<result property="id" column="id"/>
<result property="fileName" column="file_name"/>
<result property="url" column="url"/>
<result property="createTime" column="create_time"/>
<result property="createBy" column="create_by"/>
<result property="updateTime" column="update_time"/>
<result property="updateBy" column="update_by"/>
</resultMap>
</mapper>

View File

@ -82,7 +82,7 @@
<el-table v-loading="loading" :data="lableList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="主键id" align="center" prop="id" v-if="true"/>
<el-table-column label="主键id" align="center" prop="id" v-if="false"/>
<el-table-column label="图片上传地址" align="center" prop="imageurl" />
<el-table-column label="文件类型" align="center" prop="fileType" />
<el-table-column label="标签名称" align="center" prop="menuName" />

View File

@ -1,14 +1,7 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="封面" prop="cover">
<el-input
v-model="queryParams.cover"
placeholder="请输入封面"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="标题名称" prop="captionName">
<el-input
v-model="queryParams.captionName"
@ -33,38 +26,15 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="摘要" prop="abstract">
<el-form-item label="摘要" prop="abstracts">
<el-input
v-model="queryParams.abstract"
v-model="queryParams.abstracts"
placeholder="请输入摘要"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="是否置顶 0否 1是" prop="isTop">
<el-input
v-model="queryParams.isTop"
placeholder="请输入是否置顶 0否 1是"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="创建者id" prop="createUserId">
<el-input
v-model="queryParams.createUserId"
placeholder="请输入创建者id"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="更新者id" prop="updateUserId">
<el-input
v-model="queryParams.updateUserId"
placeholder="请输入更新者id"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@ -119,7 +89,7 @@
<el-table v-loading="loading" :data="slideshowList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="主键id" align="center" prop="id" v-if="true"/>
<el-table-column label="主键id" align="center" prop="id" v-if="false"/>
<el-table-column label="封面" align="center" prop="cover" />
<el-table-column label="标题名称" align="center" prop="captionName" />
<el-table-column label="发布时间" align="center" prop="releaseTime" width="180">
@ -129,7 +99,7 @@
</el-table-column>
<el-table-column label="集团名称" align="center" prop="groupName" />
<el-table-column label="新闻内容" align="center" prop="newsContent" />
<el-table-column label="摘要" align="center" prop="abstract" />
<el-table-column label="摘要" align="center" prop="abstracts" />
<el-table-column label="是否置顶 0否 1是" align="center" prop="isTop" />
<el-table-column label="创建者id" align="center" prop="createUserId" />
<el-table-column label="更新者id" align="center" prop="updateUserId" />
@ -185,18 +155,12 @@
<el-form-item label="新闻内容">
<editor v-model="form.newsContent" :min-height="192"/>
</el-form-item>
<el-form-item label="摘要" prop="abstract">
<el-input v-model="form.abstract" placeholder="请输入摘要" />
<el-form-item label="摘要" prop="abstracts">
<el-input v-model="form.abstracts" placeholder="请输入摘要" />
</el-form-item>
<el-form-item label="是否置顶 0否 1是" prop="isTop">
<el-input v-model="form.isTop" placeholder="请输入是否置顶 0否 1是" />
</el-form-item>
<el-form-item label="创建者id" prop="createUserId">
<el-input v-model="form.createUserId" placeholder="请输入创建者id" />
</el-form-item>
<el-form-item label="更新者id" prop="updateUserId">
<el-input v-model="form.updateUserId" placeholder="请输入更新者id" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
@ -242,10 +206,8 @@ export default {
releaseTime: undefined,
groupName: undefined,
newsContent: undefined,
abstract: undefined,
abstracts: undefined,
isTop: undefined,
createUserId: undefined,
updateUserId: undefined,
},
//
form: {},
@ -269,18 +231,12 @@ export default {
newsContent: [
{ required: true, message: "新闻内容不能为空", trigger: "blur" }
],
abstract: [
abstracts: [
{ required: true, message: "摘要不能为空", trigger: "blur" }
],
isTop: [
{ required: true, message: "是否置顶 0否 1是不能为空", trigger: "blur" }
],
createUserId: [
{ required: true, message: "创建者id不能为空", trigger: "blur" }
],
updateUserId: [
{ required: true, message: "更新者id不能为空", trigger: "blur" }
],
}
};
},
@ -312,7 +268,7 @@ export default {
releaseTime: undefined,
groupName: undefined,
newsContent: undefined,
abstract: undefined,
abstracts: undefined,
isTop: undefined,
createBy: undefined,
createUserId: undefined,