mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-19 19:50:06 +08:00
1. 基于 db 实现文件的存储
This commit is contained in:
parent
f942b34d02
commit
629fa9b407
@ -1,118 +0,0 @@
|
|||||||
package com.ruoyi.web.controller.common;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
|
||||||
import com.ruoyi.common.constant.Constants;
|
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
|
||||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
|
||||||
import com.ruoyi.common.utils.file.FileUtils;
|
|
||||||
import com.ruoyi.framework.config.ServerConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通用请求处理
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
public class CommonController
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ServerConfig serverConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通用下载请求
|
|
||||||
*
|
|
||||||
* @param fileName 文件名称
|
|
||||||
* @param delete 是否删除
|
|
||||||
*/
|
|
||||||
@GetMapping("common/download")
|
|
||||||
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!FileUtils.checkAllowDownload(fileName))
|
|
||||||
{
|
|
||||||
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
|
|
||||||
}
|
|
||||||
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
|
|
||||||
String filePath = RuoYiConfig.getDownloadPath() + fileName;
|
|
||||||
|
|
||||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
|
||||||
FileUtils.setAttachmentResponseHeader(response, realFileName);
|
|
||||||
FileUtils.writeBytes(filePath, response.getOutputStream());
|
|
||||||
if (delete)
|
|
||||||
{
|
|
||||||
FileUtils.deleteFile(filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
log.error("下载文件失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通用上传请求
|
|
||||||
*/
|
|
||||||
@PostMapping("/common/upload")
|
|
||||||
public AjaxResult uploadFile(MultipartFile file) throws Exception
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 上传文件路径
|
|
||||||
String filePath = RuoYiConfig.getUploadPath();
|
|
||||||
// 上传并返回新文件名称
|
|
||||||
String fileName = FileUploadUtils.upload(filePath, file);
|
|
||||||
String url = serverConfig.getUrl() + fileName;
|
|
||||||
AjaxResult ajax = AjaxResult.success();
|
|
||||||
ajax.put("fileName", fileName);
|
|
||||||
ajax.put("url", url);
|
|
||||||
return ajax;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
return AjaxResult.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 本地资源通用下载
|
|
||||||
*/
|
|
||||||
@GetMapping("/common/download/resource")
|
|
||||||
public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!FileUtils.checkAllowDownload(resource))
|
|
||||||
{
|
|
||||||
throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
|
|
||||||
}
|
|
||||||
// 本地资源路径
|
|
||||||
String localPath = RuoYiConfig.getProfile();
|
|
||||||
// 数据库资源地址
|
|
||||||
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
|
|
||||||
// 下载名称
|
|
||||||
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
|
||||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
|
||||||
FileUtils.setAttachmentResponseHeader(response, downloadName);
|
|
||||||
FileUtils.writeBytes(downloadPath, response.getOutputStream());
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
log.error("下载文件失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -34,7 +34,7 @@ export function logout() {
|
|||||||
// 获取验证码
|
// 获取验证码
|
||||||
export function getCodeImg() {
|
export function getCodeImg() {
|
||||||
return request({
|
return request({
|
||||||
url: '/captcha/get-image',
|
url: '/system/captcha/get-image',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ export function exportPost(query) {
|
|||||||
return request({
|
return request({
|
||||||
url: '/system/post/export',
|
url: '/system/post/export',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query,
|
||||||
|
responseType: 'blob'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@ export default {
|
|||||||
}).then(function() {
|
}).then(function() {
|
||||||
return exportPost(queryParams);
|
return exportPost(queryParams);
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.downloadExcel(response, '岗位数据.xls');
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package cn.iocoder.dashboard.framework.file.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件 配置类
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties(FileProperties.class)
|
||||||
|
public class FileConfiguration {
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package cn.iocoder.dashboard.framework.file.config;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.modules.system.controller.common.SysFileController;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "yudao.file")
|
||||||
|
@Validated
|
||||||
|
@Data
|
||||||
|
public class FileProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对应 {@link SysFileController#}
|
||||||
|
*/
|
||||||
|
@NotNull(message = "基础文件路径不能为空")
|
||||||
|
private String basePath;
|
||||||
|
|
||||||
|
// TODO 七牛、等等
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* 文件的存储,推荐使用七牛、阿里云、华为云、腾讯云等文件服务
|
||||||
|
*
|
||||||
|
* 在不采用云服务的情况下,我们有几种技术选型:
|
||||||
|
* 方案 1. 使用自建的文件服务,例如说 minIO、FastDFS 等等
|
||||||
|
* 方案 2. 使用服务器的文件系统存储
|
||||||
|
* 方案 3. 使用数据库进行存储
|
||||||
|
*
|
||||||
|
* 如果考虑额外在搭建服务,推荐方案 1。
|
||||||
|
* 对于方案 2 来说,如果要实现文件存储的高可用,需要多台服务器之间做实时同步,可以基于 rsync + inotify 来做
|
||||||
|
* 对于方案 3 的话,实现起来最简单,但是数据库本身不适合存储海量的文件
|
||||||
|
*
|
||||||
|
* 综合考虑,暂时使用方案 3 的方式,比较适合这样一个 all in one 的项目。
|
||||||
|
* 随着文件的量级大了之后,还是推荐采用云服务。
|
||||||
|
*/
|
||||||
|
package cn.iocoder.dashboard.framework.file;
|
@ -1,7 +1,6 @@
|
|||||||
package cn.iocoder.dashboard.framework.security.config;
|
package cn.iocoder.dashboard.framework.security.config;
|
||||||
|
|
||||||
import cn.iocoder.dashboard.framework.security.core.filter.JwtAuthenticationTokenFilter;
|
import cn.iocoder.dashboard.framework.security.core.filter.JwtAuthenticationTokenFilter;
|
||||||
import cn.iocoder.dashboard.framework.security.core.handler.AuthenticationEntryPointImpl;
|
|
||||||
import cn.iocoder.dashboard.framework.security.core.handler.LogoutSuccessHandlerImpl;
|
import cn.iocoder.dashboard.framework.security.core.handler.LogoutSuccessHandlerImpl;
|
||||||
import cn.iocoder.dashboard.framework.web.config.WebProperties;
|
import cn.iocoder.dashboard.framework.web.config.WebProperties;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
@ -19,8 +18,6 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
|||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
|
||||||
import org.springframework.web.filter.CorsFilter;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
@ -126,12 +123,13 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||||||
// 登陆的接口,可匿名访问
|
// 登陆的接口,可匿名访问
|
||||||
.antMatchers(webProperties.getApiPrefix() + "/login").anonymous()
|
.antMatchers(webProperties.getApiPrefix() + "/login").anonymous()
|
||||||
// 通用的接口,可匿名访问
|
// 通用的接口,可匿名访问
|
||||||
.antMatchers( webProperties.getApiPrefix() + "/captcha/**").anonymous()
|
.antMatchers( webProperties.getApiPrefix() + "/system/captcha/**").anonymous()
|
||||||
// TODO
|
// TODO
|
||||||
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||||
.antMatchers("/profile/**").anonymous()
|
.antMatchers("/profile/**").anonymous()
|
||||||
.antMatchers("/common/download**").anonymous()
|
// 文件的获取接口,可匿名访问
|
||||||
.antMatchers("/common/download/resource**").anonymous()
|
.antMatchers(webProperties.getApiPrefix() + "/system/file/get/**").anonymous()
|
||||||
|
// TODO
|
||||||
.antMatchers("/swagger-ui.html").anonymous()
|
.antMatchers("/swagger-ui.html").anonymous()
|
||||||
.antMatchers("/swagger-resources/**").anonymous()
|
.antMatchers("/swagger-resources/**").anonymous()
|
||||||
.antMatchers("/webjars/**").anonymous()
|
.antMatchers("/webjars/**").anonymous()
|
||||||
|
@ -15,7 +15,7 @@ import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
|
|||||||
|
|
||||||
@Api(tags = "验证码 API")
|
@Api(tags = "验证码 API")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/captcha")
|
@RequestMapping("/system/captcha")
|
||||||
public class SysCaptchaController {
|
public class SysCaptchaController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.controller.common;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.common.SysFileDO;
|
||||||
|
import cn.iocoder.dashboard.modules.system.service.common.SysFileService;
|
||||||
|
import cn.iocoder.dashboard.util.servlet.ServletUtils;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@Api(tags = "文件 API")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/file")
|
||||||
|
@Slf4j
|
||||||
|
public class SysFileController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SysFileService fileService;
|
||||||
|
|
||||||
|
@PostMapping("/upload")
|
||||||
|
public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
|
||||||
|
@RequestParam("path") String path) throws IOException {
|
||||||
|
return success(fileService.createFile(path, IoUtil.readBytes(file.getInputStream())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get/{path}")
|
||||||
|
public void getFile(HttpServletResponse response, @PathVariable("path") String path) throws IOException {
|
||||||
|
SysFileDO file = fileService.getFile(path);
|
||||||
|
if (file == null) {
|
||||||
|
log.warn("[getFile][path({}) 文件不存在]", path);
|
||||||
|
response.setStatus(HttpStatus.NOT_FOUND.value());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ServletUtils.writeAttachment(response, path, file.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.dept;
|
|||||||
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
|
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.*;
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.*;
|
||||||
import cn.iocoder.dashboard.modules.system.convert.dept.SysPostConvert;
|
import cn.iocoder.dashboard.modules.system.convert.dept.SysPostConvert;
|
||||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysPostDO;
|
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysPostDO;
|
||||||
@ -14,6 +15,8 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -80,12 +83,16 @@ public class SysPostController {
|
|||||||
return success(SysPostConvert.INSTANCE.convert(postService.getPost(id)));
|
return success(SysPostConvert.INSTANCE.convert(postService.getPost(id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/export")
|
||||||
|
@ApiOperation("岗位管理")
|
||||||
// @Log(title = "岗位管理", businessType = BusinessType.EXPORT)
|
// @Log(title = "岗位管理", businessType = BusinessType.EXPORT)
|
||||||
// @PreAuthorize("@ss.hasPermi('system:post:export')")
|
// @PreAuthorize("@ss.hasPermi('system:post:export')")
|
||||||
// @GetMapping("/export")
|
public void export(HttpServletResponse response, @Validated SysPostExportReqVO reqVO) throws IOException {
|
||||||
// public AjaxResult export(SysPost post) {
|
List<SysPostDO> posts = postService.listPosts(reqVO);
|
||||||
// List<SysPost> list = postService.selectPostList(post);
|
List<SysPostExcelVO> excelPosts = SysPostConvert.INSTANCE.convertList03(posts);
|
||||||
// ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
|
// 输出
|
||||||
// return util.exportExcel(list, "岗位数据");
|
ExcelUtils.write(response, "岗位数据.xls", "岗位列表",
|
||||||
// }
|
SysPostExcelVO.class, excelPosts);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
package cn.iocoder.dashboard.modules.system.controller.dept.vo.post;
|
|
||||||
|
|
||||||
import cn.iocoder.dashboard.framework.excel.Excel;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 岗位 Excel 导出响应 VO
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class SysPostExcelRespVO {
|
|
||||||
|
|
||||||
@Excel(name = "岗位序号", cellType = Excel.ColumnType.NUMERIC)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Excel(name = "岗位编码")
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
@Excel(name = "岗位名称")
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@Excel(name = "岗位排序")
|
|
||||||
private String sort;
|
|
||||||
|
|
||||||
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
|
|
||||||
private String status;
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,32 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.controller.dept.vo.post;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
|
||||||
|
import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import static cn.iocoder.dashboard.modules.system.enums.dict.DictTypeEnum.SYS_COMMON_STATUS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 岗位 Excel 导出响应 VO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SysPostExcelVO {
|
||||||
|
|
||||||
|
@ExcelProperty("岗位序号")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ExcelProperty("岗位编码")
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
@ExcelProperty("岗位名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ExcelProperty("岗位排序")
|
||||||
|
private String sort;
|
||||||
|
|
||||||
|
@ExcelProperty(value = "状态", converter = DictConvert.class)
|
||||||
|
@DictFormat(SYS_COMMON_STATUS)
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.controller.dept.vo.post;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@ApiModel(value = "岗位导出 Request VO", description = "参数和 SysPostExcelVO 是一致的")
|
||||||
|
@Data
|
||||||
|
public class SysPostExportReqVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "岗位名称", example = "芋道", notes = "模糊匹配")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,7 @@
|
|||||||
package cn.iocoder.dashboard.modules.system.convert.dept;
|
package cn.iocoder.dashboard.modules.system.convert.dept;
|
||||||
|
|
||||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostCreateReqVO;
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.*;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostRespVO;
|
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostSimpleRespVO;
|
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostUpdateReqVO;
|
|
||||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysPostDO;
|
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysPostDO;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
@ -31,4 +28,6 @@ public interface SysPostConvert {
|
|||||||
|
|
||||||
SysPostDO convert(SysPostUpdateReqVO reqVO);
|
SysPostDO convert(SysPostUpdateReqVO reqVO);
|
||||||
|
|
||||||
|
List<SysPostExcelVO> convertList03(List<SysPostDO> list);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.dal.mysql.dao.common;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.common.SysFileDO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface SysFileMapper extends BaseMapper<SysFileDO> {
|
||||||
|
|
||||||
|
default Integer selectCountById(String id) {
|
||||||
|
return selectCount(new QueryWrapper<SysFileDO>().eq("id", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dao.dept;
|
|||||||
|
|
||||||
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
|
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
|
||||||
import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils;
|
import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils;
|
||||||
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostExportReqVO;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostPageReqVO;
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostPageReqVO;
|
||||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysPostDO;
|
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysPostDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
@ -26,6 +27,11 @@ public interface SysPostMapper extends BaseMapper<SysPostDO> {
|
|||||||
.eqIfPresent("status", reqVO.getStatus()));
|
.eqIfPresent("status", reqVO.getStatus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default List<SysPostDO> selectList(SysPostExportReqVO reqVO) {
|
||||||
|
return selectList(new QueryWrapperX<SysPostDO>().likeIfPresent("name", reqVO.getName())
|
||||||
|
.eqIfPresent("status", reqVO.getStatus()));
|
||||||
|
}
|
||||||
|
|
||||||
default SysPostDO selectByName(String name) {
|
default SysPostDO selectByName(String name) {
|
||||||
return selectOne(new QueryWrapper<SysPostDO>().eq("name", name));
|
return selectOne(new QueryWrapper<SysPostDO>().eq("name", name));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.common;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件表
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("sys_file")
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class SysFileDO extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件路径
|
||||||
|
*/
|
||||||
|
@TableId(type = IdType.INPUT)
|
||||||
|
private String id;
|
||||||
|
/**
|
||||||
|
* 文件内容
|
||||||
|
*/
|
||||||
|
private byte[] content;
|
||||||
|
|
||||||
|
}
|
@ -8,7 +8,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门表 sys_dept
|
* 部门表
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
|
@ -69,4 +69,6 @@ public interface SysErrorCodeConstants {
|
|||||||
// ========== 通知公告 1002008000 ==========
|
// ========== 通知公告 1002008000 ==========
|
||||||
ErrorCode NOTICE_NOT_FOUND = new ErrorCode(1002008001, "当前通知公告不存在");
|
ErrorCode NOTICE_NOT_FOUND = new ErrorCode(1002008001, "当前通知公告不存在");
|
||||||
|
|
||||||
|
// ========== 文件 1002009000 ==========
|
||||||
|
ErrorCode FILE_PATH_EXISTS = new ErrorCode(1002009001, "文件路径已经存在");
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.service.common;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.common.SysFileDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件 Service 接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface SysFileService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存文件,并返回文件的访问路径
|
||||||
|
*
|
||||||
|
* @param path 文件路径
|
||||||
|
* @param content 文件内容
|
||||||
|
* @return 文件路径
|
||||||
|
*/
|
||||||
|
String createFile(String path, byte[] content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得文件
|
||||||
|
*
|
||||||
|
* @param path 文件路径
|
||||||
|
* @return 文件
|
||||||
|
*/
|
||||||
|
SysFileDO getFile(String path);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.service.common.impl;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
|
||||||
|
import cn.iocoder.dashboard.framework.file.config.FileProperties;
|
||||||
|
import cn.iocoder.dashboard.modules.system.dal.mysql.dao.common.SysFileMapper;
|
||||||
|
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.common.SysFileDO;
|
||||||
|
import cn.iocoder.dashboard.modules.system.service.common.SysFileService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_PATH_EXISTS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件 Service 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class SysFileServiceImpl implements SysFileService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SysFileMapper fileMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FileProperties fileProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String createFile(String path, byte[] content) {
|
||||||
|
if (fileMapper.selectCountById(path) > 0) {
|
||||||
|
throw ServiceExceptionUtil.exception(FILE_PATH_EXISTS);
|
||||||
|
}
|
||||||
|
// 保存到数据库
|
||||||
|
SysFileDO file = new SysFileDO();
|
||||||
|
file.setId(path);
|
||||||
|
file.setContent(content);
|
||||||
|
fileMapper.insert(file);
|
||||||
|
// 拼接路径返回
|
||||||
|
return fileProperties.getBasePath() + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SysFileDO getFile(String path) {
|
||||||
|
return fileMapper.selectById(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.service.dept;
|
|||||||
|
|
||||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostCreateReqVO;
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostCreateReqVO;
|
||||||
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostExportReqVO;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostPageReqVO;
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostPageReqVO;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostUpdateReqVO;
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostUpdateReqVO;
|
||||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysPostDO;
|
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysPostDO;
|
||||||
@ -18,7 +19,7 @@ import java.util.List;
|
|||||||
public interface SysPostService {
|
public interface SysPostService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得所有岗位列表
|
* 获得符合条件的岗位列表
|
||||||
*
|
*
|
||||||
* @param ids 岗位编号数组。如果为空,不进行筛选
|
* @param ids 岗位编号数组。如果为空,不进行筛选
|
||||||
* @param statuses 状态数组。如果为空,不进行筛选
|
* @param statuses 状态数组。如果为空,不进行筛选
|
||||||
@ -34,6 +35,14 @@ public interface SysPostService {
|
|||||||
*/
|
*/
|
||||||
PageResult<SysPostDO> pagePosts(SysPostPageReqVO reqVO);
|
PageResult<SysPostDO> pagePosts(SysPostPageReqVO reqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得岗位列表
|
||||||
|
*
|
||||||
|
* @param reqVO 查询条件
|
||||||
|
* @return 部门列表
|
||||||
|
*/
|
||||||
|
List<SysPostDO> listPosts(SysPostExportReqVO reqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得岗位信息
|
* 获得岗位信息
|
||||||
*
|
*
|
||||||
|
@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.service.dept.impl;
|
|||||||
import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
|
import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
|
||||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostCreateReqVO;
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostCreateReqVO;
|
||||||
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostExportReqVO;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostPageReqVO;
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostPageReqVO;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostUpdateReqVO;
|
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostUpdateReqVO;
|
||||||
import cn.iocoder.dashboard.modules.system.convert.dept.SysPostConvert;
|
import cn.iocoder.dashboard.modules.system.convert.dept.SysPostConvert;
|
||||||
@ -38,6 +39,11 @@ public class SysPostServiceImpl implements SysPostService {
|
|||||||
return SysPostConvert.INSTANCE.convertPage02(postMapper.selectList(reqVO));
|
return SysPostConvert.INSTANCE.convertPage02(postMapper.selectList(reqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SysPostDO> listPosts(SysPostExportReqVO reqVO) {
|
||||||
|
return postMapper.selectList(reqVO);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SysPostDO getPost(Long id) {
|
public SysPostDO getPost(Long id) {
|
||||||
return postMapper.selectById(id);
|
return postMapper.selectById(id);
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package cn.iocoder.dashboard.util.servlet;
|
package cn.iocoder.dashboard.util.servlet;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.extra.servlet.ServletUtil;
|
import cn.hutool.extra.servlet.ServletUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客户端工具类
|
* 客户端工具类
|
||||||
@ -14,10 +16,32 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
*/
|
*/
|
||||||
public class ServletUtils {
|
public class ServletUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回 JSON 字符串
|
||||||
|
*
|
||||||
|
* @param response 响应
|
||||||
|
* @param object 对象,会序列化成 JSON 字符串
|
||||||
|
*/
|
||||||
@SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码
|
@SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码
|
||||||
public static void writeJSON(HttpServletResponse response, Object object) {
|
public static void writeJSON(HttpServletResponse response, Object object) {
|
||||||
String content = JSON.toJSONString(object);
|
String content = JSON.toJSONString(object);
|
||||||
ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE);
|
ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回附件
|
||||||
|
*
|
||||||
|
* @param response 响应
|
||||||
|
* @param filename 文件名
|
||||||
|
* @param content 附件内容
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException {
|
||||||
|
// 设置 header 和 contentType
|
||||||
|
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
|
||||||
|
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||||
|
// 输出附件
|
||||||
|
IoUtil.write(response.getOutputStream(), false, content);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,12 @@ spring:
|
|||||||
database: 0
|
database: 0
|
||||||
# 连接超时时间
|
# 连接超时时间
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
|
# Servlet 配置
|
||||||
|
servlet:
|
||||||
|
# 文件上传相关配置项
|
||||||
|
multipart:
|
||||||
|
max-file-size: 16MB # 单个文件大小
|
||||||
|
max-request-size: 32MB # 设置总上传的文件大小
|
||||||
|
|
||||||
# 芋道配置项,设置当前项目所有自定义的配置
|
# 芋道配置项,设置当前项目所有自定义的配置
|
||||||
yudao:
|
yudao:
|
||||||
@ -38,6 +44,8 @@ yudao:
|
|||||||
timeout: 5m
|
timeout: 5m
|
||||||
width: 160
|
width: 160
|
||||||
height: 60
|
height: 60
|
||||||
|
file:
|
||||||
|
base-path: http://127.0.0.1:1024/api/file/get/
|
||||||
|
|
||||||
# MyBatis Plus 的配置项
|
# MyBatis Plus 的配置项
|
||||||
mybatis-plus:
|
mybatis-plus:
|
||||||
|
Loading…
Reference in New Issue
Block a user