diff --git a/pom.xml b/pom.xml index c8d6ba3..9d765b5 100644 --- a/pom.xml +++ b/pom.xml @@ -161,6 +161,12 @@ 3.14.9 + + cn.hutool + hutool-core + 5.3.6 + + diff --git a/src/main/java/com/huoran/iasf/common/exception/handler/RestExceptionHandler.java b/src/main/java/com/huoran/iasf/common/exception/handler/RestExceptionHandler.java index 3f7ceb5..44ee344 100644 --- a/src/main/java/com/huoran/iasf/common/exception/handler/RestExceptionHandler.java +++ b/src/main/java/com/huoran/iasf/common/exception/handler/RestExceptionHandler.java @@ -41,7 +41,8 @@ public class RestExceptionHandler { @ExceptionHandler(value = BusinessException.class) R businessExceptionHandler(BusinessException e) { log.error("Exception,exception:{}", e, e); - return new R(e.getMessageCode(), e.getDetailMessage()); + + return new R(e.getMessageCode(), e.getMessage()); } /** diff --git a/src/main/java/com/huoran/iasf/common/filter/AuthFilter.java b/src/main/java/com/huoran/iasf/common/filter/AuthFilter.java index e084fe1..5b3a8a6 100644 --- a/src/main/java/com/huoran/iasf/common/filter/AuthFilter.java +++ b/src/main/java/com/huoran/iasf/common/filter/AuthFilter.java @@ -1,3 +1,4 @@ +/* package com.huoran.iasf.common.filter; import com.alibaba.fastjson.JSON; @@ -20,12 +21,14 @@ import static com.huoran.iasf.service.HttpApiSessionService.USER_ID_KEY; import static com.huoran.iasf.service.HttpApiSessionService.USER_USERNAME_KEY; @Slf4j -@WebFilter(filterName = "authFilter", urlPatterns = "/iasf/app/api/*") +@WebFilter(filterName = "authFilter", urlPatterns = "/iasf/*") @Order(1) public class AuthFilter implements Filter { - /** - * 白名单 - */ +*/ +/** + * 白名单*//* + + private static final String[] whiteList = {"/iasf/app/api/login", "/iasf/app/api/open/test"}; @Resource HttpApiSessionService httpApiSessionService; @@ -69,11 +72,14 @@ public class AuthFilter implements Filter { } - /** +*/ +/** * responseResult * @param response * @param result - */ + *//* + + private void responseResult(HttpServletResponse response, R result) { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-type", "application/json;charset=UTF-8"); @@ -84,4 +90,5 @@ public class AuthFilter implements Filter { log.error(ex.getMessage()); } } -} \ No newline at end of file +} +*/ diff --git a/src/main/java/com/huoran/iasf/common/shiro/ShiroConfig.java b/src/main/java/com/huoran/iasf/common/shiro/ShiroConfig.java index c817928..7bce29b 100644 --- a/src/main/java/com/huoran/iasf/common/shiro/ShiroConfig.java +++ b/src/main/java/com/huoran/iasf/common/shiro/ShiroConfig.java @@ -1,3 +1,4 @@ +/* package com.huoran.iasf.common.shiro; import com.huoran.iasf.common.config.FileUploadProperties; @@ -14,13 +15,16 @@ import javax.servlet.Filter; import java.util.LinkedHashMap; import java.util.Map; +*/ /** * ShiroConfig * * @author cheney * @version V1.0 * @date 2022年7月28日 - */ + *//* + + @Configuration @EnableConfigurationProperties(FileUploadProperties.class) public class ShiroConfig { @@ -33,9 +37,11 @@ public class ShiroConfig { return new CustomHashedCredentialsMatcher(); } - /** - * 创建realm - */ +*/ +/** + * 创建realm*//* + + @Bean public CustomRealm customRealm() { CustomRealm customRealm = new CustomRealm(); @@ -97,12 +103,15 @@ public class ShiroConfig { return shiroFilterFactoryBean; } - /** +*/ +/** * 开启shiro aop注解支持. * 使用代理方式;所以需要开启代码支持; * - * @return org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor - */ + * @return org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor*//* + + + @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); @@ -113,3 +122,4 @@ public class ShiroConfig { } +*/ diff --git a/src/main/java/com/huoran/iasf/controller/SysFilesController.java b/src/main/java/com/huoran/iasf/controller/SysFilesController.java index 5e25340..7ccd62b 100644 --- a/src/main/java/com/huoran/iasf/controller/SysFilesController.java +++ b/src/main/java/com/huoran/iasf/controller/SysFilesController.java @@ -1,19 +1,24 @@ package com.huoran.iasf.controller; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.huoran.iasf.common.utils.R; import com.huoran.iasf.entity.SysFilesEntity; import com.huoran.iasf.service.SysFilesService; +import com.huoran.iasf.vo.req.FileParameters; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.util.List; @@ -34,29 +39,51 @@ public class SysFilesController { @ApiOperation(value = "新增") @PostMapping("/upload") @RequiresPermissions(value = {"sysFiles:add", "sysContent:update", "sysContent:add"}, logical = Logical.OR) - public R add(@RequestParam(value = "file") MultipartFile file) { + public R add(@RequestParam(value = "file") MultipartFile file, FileParameters fileParameters) { //判断文件是否空 if (file == null || file.getOriginalFilename() == null || "".equalsIgnoreCase(file.getOriginalFilename().trim())) { return R.fail("文件为空"); } - return sysFilesService.saveFile(file); + return sysFilesService.saveFile(file,fileParameters); + } + + @ApiOperation(value = "文件预览") + @GetMapping("/preview/{id}") + public void preview(@PathVariable Integer id, HttpServletRequest req, HttpServletResponse res) { + sysFilesService.preview(id, req, res); + } + + @ApiOperation(value = "文件下载") + @GetMapping("/download/{id}") + public void download(@PathVariable Integer id, HttpServletRequest req, HttpServletResponse res) { + sysFilesService.download(id, req, res); } @ApiOperation(value = "删除") @DeleteMapping("/delete") @RequiresPermissions("sysFiles:delete") - public R delete(@RequestBody @ApiParam(value = "id集合") List ids) { + public R delete(@RequestBody @ApiParam(value = "id集合") List ids) { sysFilesService.removeByIdsAndFiles(ids); return R.success(); } - @ApiOperation(value = "查询分页数据") + @ApiOperation(value = "查询分页数据",response = SysFilesEntity.class) @PostMapping("/listByPage") @RequiresPermissions("sysFiles:list") public R findListByPage(@RequestBody SysFilesEntity sysFiles) { - IPage iPage = sysFilesService.page(sysFiles.getQueryPage(), Wrappers.lambdaQuery().orderByDesc(SysFilesEntity::getCreateDate)); + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); + if (!StringUtils.isEmpty(sysFiles.getFileName())) { + queryWrapper.like(SysFilesEntity::getFileName, sysFiles.getFileName()); + } + if (!StringUtils.isEmpty(sysFiles.getType())) { + queryWrapper.eq(SysFilesEntity::getType, sysFiles.getType()); + } + if (!StringUtils.isEmpty(sysFiles.getSite())) { + queryWrapper.eq(SysFilesEntity::getSite, sysFiles.getSite()); + } + queryWrapper.orderByDesc(SysFilesEntity::getCreateDate); + IPage iPage = sysFilesService.page(sysFiles.getQueryPage(),queryWrapper); return R.success(iPage); } - } diff --git a/src/main/java/com/huoran/iasf/entity/BaseEntity.java b/src/main/java/com/huoran/iasf/entity/BaseEntity.java index 7c084c9..e1d8cf1 100644 --- a/src/main/java/com/huoran/iasf/entity/BaseEntity.java +++ b/src/main/java/com/huoran/iasf/entity/BaseEntity.java @@ -3,6 +3,7 @@ package com.huoran.iasf.entity; import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; @@ -19,16 +20,19 @@ public class BaseEntity { @JSONField(serialize = false) @TableField(exist = false) + @ApiModelProperty(value = "页码",example = "1") private int page = 1; @JSONField(serialize = false) @TableField(exist = false) + @ApiModelProperty(value = "页数",example = "10") private int limit = 10; /** * 数据权限:用户id */ @TableField(exist = false) + @ApiModelProperty(value = "用户id") private List createIds; /** @@ -36,6 +40,7 @@ public class BaseEntity { * @param * @return */ + @ApiModelProperty(value = "getQueryPage", hidden = true) public Page getQueryPage() { return new Page(page, limit); } diff --git a/src/main/java/com/huoran/iasf/entity/SysFilesEntity.java b/src/main/java/com/huoran/iasf/entity/SysFilesEntity.java index 21c2906..b3e6960 100644 --- a/src/main/java/com/huoran/iasf/entity/SysFilesEntity.java +++ b/src/main/java/com/huoran/iasf/entity/SysFilesEntity.java @@ -1,9 +1,6 @@ package com.huoran.iasf.entity; -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -24,34 +21,45 @@ import java.util.Date; public class SysFilesEntity extends BaseEntity implements Serializable { private static final long serialVersionUID = 1L; - /** - * 主键 - */ - @TableId("id") @ApiModelProperty(value = "主键") - private String id; + @TableId(value = "id", type = IdType.AUTO) + private int id; - /** - * URL地址 - */ - @TableField("url") @ApiModelProperty(value = "url地址") private String url; - /** - * 创建时间 - */ - @TableField(value = "create_date", fill = FieldFill.INSERT) - @ApiModelProperty(value = "创建时间") - private Date createDate; - @TableField("file_name") @ApiModelProperty(value = "文件名称") private String fileName; - @TableField("file_path") @ApiModelProperty(value = "文件路径") private String filePath; + @TableField("type") + @ApiModelProperty(value = "文件类型") + private String type; + + @ApiModelProperty(value = "文件格式") + private String format; + + @ApiModelProperty(value = "文件大小") + private Integer fileSize; + + @ApiModelProperty(value = "上传人") + private String uploader; + @ApiModelProperty(value = "引用地方") + private String quote; + + @TableField("site") + @ApiModelProperty(value = "站点来源") + private String site; + + @ApiModelProperty(value = "是否已删除,未删除表示该文件正在使用") + @TableField(fill = FieldFill.INSERT) + private Integer deleted; + + @TableField(value = "create_date", fill = FieldFill.INSERT) + @ApiModelProperty(value = "创建时间") + private Date createDate; } diff --git a/src/main/java/com/huoran/iasf/service/SysFilesService.java b/src/main/java/com/huoran/iasf/service/SysFilesService.java index 286f0f1..96b3172 100644 --- a/src/main/java/com/huoran/iasf/service/SysFilesService.java +++ b/src/main/java/com/huoran/iasf/service/SysFilesService.java @@ -3,8 +3,11 @@ package com.huoran.iasf.service; import com.baomidou.mybatisplus.extension.service.IService; import com.huoran.iasf.common.utils.R; import com.huoran.iasf.entity.SysFilesEntity; +import com.huoran.iasf.vo.req.FileParameters; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.util.List; /** @@ -16,8 +19,12 @@ import java.util.List; */ public interface SysFilesService extends IService { - R saveFile(MultipartFile file); + R saveFile(MultipartFile file, FileParameters fileParameters); - void removeByIdsAndFiles(List ids); + void removeByIdsAndFiles(List ids); + + void preview(Integer id, HttpServletRequest req, HttpServletResponse res); + + void download(Integer id, HttpServletRequest req, HttpServletResponse res); } diff --git a/src/main/java/com/huoran/iasf/service/impl/SysFilesServiceImpl.java b/src/main/java/com/huoran/iasf/service/impl/SysFilesServiceImpl.java index c296439..f09924f 100644 --- a/src/main/java/com/huoran/iasf/service/impl/SysFilesServiceImpl.java +++ b/src/main/java/com/huoran/iasf/service/impl/SysFilesServiceImpl.java @@ -1,20 +1,28 @@ package com.huoran.iasf.service.impl; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.huoran.iasf.common.config.FileUploadProperties; import com.huoran.iasf.common.exception.BusinessException; -import com.huoran.iasf.common.utils.R; import com.huoran.iasf.common.utils.DateUtils; +import com.huoran.iasf.common.utils.R; import com.huoran.iasf.entity.SysFilesEntity; import com.huoran.iasf.mapper.SysFilesMapper; import com.huoran.iasf.service.SysFilesService; +import com.huoran.iasf.vo.req.FileParameters; import org.apache.commons.io.FileUtils; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import java.io.File; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; import java.util.*; /** @@ -27,11 +35,12 @@ import java.util.*; @EnableConfigurationProperties(FileUploadProperties.class) @Service("sysFilesService") public class SysFilesServiceImpl extends ServiceImpl implements SysFilesService { + @Resource private FileUploadProperties fileUploadProperties; @Override - public R saveFile(MultipartFile file) { + public R saveFile(MultipartFile file, FileParameters fileParameters) { //存储文件夹 String createTime = DateUtils.format(new Date(), DateUtils.DATEPATTERN); String newPath = fileUploadProperties.getPath() + createTime + File.separator; @@ -45,10 +54,14 @@ public class SysFilesServiceImpl extends ServiceImpl resultMap = new HashMap<>(); - resultMap.put("src", url); + resultMap.put("url", url); return R.success(resultMap); } catch (Exception e) { throw new BusinessException("上传文件失败"); @@ -68,7 +88,80 @@ public class SysFilesServiceImpl extends ServiceImpl ids) { + public void preview(Integer id, HttpServletRequest req, HttpServletResponse res) { + if (id != null) { + SysFilesEntity entity = this.getById(id); + String path = entity.getFilePath(); + res.setContentLength(entity.getFileSize()); + File file = new File(path); + byte[] buffer = FileUtil.readBytes(path); + if (file.exists()) { + try { + //设置contentType + res.setContentType(MediaType.ALL_VALUE); + res.setCharacterEncoding("UTF-8"); + //获取outputStream + ServletOutputStream outputStream = res.getOutputStream(); + //输出 + IoUtil.write(outputStream, true, buffer); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + } + } + + @Override + public void download(Integer id, HttpServletRequest req, HttpServletResponse res) { + if (id != null) { + SysFilesEntity entity = this.getById(id); + String path = entity.getFilePath(); + setDownloadContent(entity.getFileName(), req, res); + // 重要,需要设置此值,否则下载后打开文件会提示文件需要修复 + res.setContentLength(entity.getFileSize()); + File file = new File(path); + if (file.exists()) { + byte[] buffer = new byte[1024]; + //输出流 + OutputStream os; + try (FileInputStream fis = new FileInputStream(file); + BufferedInputStream bis = new BufferedInputStream(fis);) { + os = res.getOutputStream(); + int i = bis.read(buffer); + while (i != -1) { + os.write(buffer, 0, i); + i = bis.read(buffer); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + } + } + + /** + * 客户端下载文件上response header的设置。 + * + * @param fileName 文件名 + * @param request 请求 + * @param response 响应 + */ + private void setDownloadContent(String fileName, HttpServletRequest request, HttpServletResponse response) { + String agent = request.getHeader("User-Agent"); + try { + if (null != agent && agent.toUpperCase().indexOf("MSIE") > 0) { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } else { + fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1"); + } + } catch (UnsupportedEncodingException e1) { + } + response.setContentType("application/x-msdownload;"); + response.setHeader("Content-Disposition", "attachment; filename=" + fileName); + } + + @Override + public void removeByIdsAndFiles(List ids) { List list = this.listByIds(ids); list.forEach(entity -> { //如果之前的文件存在,删除 diff --git a/src/main/java/com/huoran/iasf/vo/req/FileParameters.java b/src/main/java/com/huoran/iasf/vo/req/FileParameters.java new file mode 100644 index 0000000..c2faa85 --- /dev/null +++ b/src/main/java/com/huoran/iasf/vo/req/FileParameters.java @@ -0,0 +1,26 @@ +package com.huoran.iasf.vo.req; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Author chen + * @DATE 2022/8/8 11:15 + * @Version 1.0 + */ +@Data +public class FileParameters { + + @ApiModelProperty(value = "站点来源",example = "粒子研究院中文站点") + private String site; + + @ApiModelProperty(value = "上传人",example = "管理员") + private String uploader; + + @ApiModelProperty(value = "引用地方",example = "某某文章") + private String quote; + + @ApiModelProperty(value = "文件类型",example = "图片") + private String type; + +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index cbefca2..e1bbb43 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -6,9 +6,9 @@ spring: datasource: master: username: root - password: root + password: HuoRan@2021 driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://121.37.12.51:3308/iasf?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8 + url: jdbc:mysql://139.9.47.170:3306/iasf?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8 redis: host: localhost # Redis服务器地址 database: 0 # Redis数据库索引(默认为0) @@ -27,4 +27,4 @@ file: path: D:/files/ #windows #path: /data/files/ #linux #文件预览、下载的url, 末尾请勿加 / - url: http://localhost:10000/files + url: http://localhost:10000/iasf/sysFiles