diff --git a/kernel-d-mongodb/mongodb-api/pom.xml b/kernel-d-mongodb/mongodb-api/pom.xml index e58bc806f..0bfac98fd 100644 --- a/kernel-d-mongodb/mongodb-api/pom.xml +++ b/kernel-d-mongodb/mongodb-api/pom.xml @@ -16,4 +16,19 @@ 8 + + + + org.springframework.boot + spring-boot-starter-web + + + + + cn.stylefeng.roses + db-api + 7.0.2 + + + \ No newline at end of file diff --git a/kernel-d-mongodb/mongodb-api/src/main/java/cn/stylefeng/roses/kernel/mongodb/api/MongoFileApi.java b/kernel-d-mongodb/mongodb-api/src/main/java/cn/stylefeng/roses/kernel/mongodb/api/MongoFileApi.java new file mode 100644 index 000000000..028f45a50 --- /dev/null +++ b/kernel-d-mongodb/mongodb-api/src/main/java/cn/stylefeng/roses/kernel/mongodb/api/MongoFileApi.java @@ -0,0 +1,43 @@ +package cn.stylefeng.roses.kernel.mongodb.api; + +import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult; +import org.springframework.web.multipart.MultipartFile; +import java.util.Optional; + +/** + * @author huziyang + * @create 2021-03-30 11:06 + */ +public interface MongoFileApi { + + /** + * 保存文件 + * @param file + * @return + */ + T saveFile(MultipartFile file); + + + /** + * 删除文件 + * @param id + */ + void removeFile(ID id); + + /** + * 根据id获取文件 + * @param id + * @return + */ + Optional getFileById(ID id); + + + /** + * 分页获取文件 + * @param fileDocument 查询条件 + * @return + */ + PageResult getFilesByPage(T fileDocument); + + +} diff --git a/kernel-d-mongodb/mongodb-integration-beetl/pom.xml b/kernel-d-mongodb/mongodb-integration-beetl/pom.xml new file mode 100644 index 000000000..1c0d67366 --- /dev/null +++ b/kernel-d-mongodb/mongodb-integration-beetl/pom.xml @@ -0,0 +1,36 @@ + + + + kernel-d-mongodb + cn.stylefeng.roses + 7.0.2 + + 4.0.0 + + mongodb-integration-beetl + + + 8 + 8 + + + + + + + cn.stylefeng.roses + scanner-api + 7.0.2 + + + + + cn.stylefeng.roses + mongodb-spring-boot-starter + 7.0.2 + + + + \ No newline at end of file diff --git a/kernel-d-mongodb/mongodb-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/mongodb/integration/controller/ModelViewController.java b/kernel-d-mongodb/mongodb-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/mongodb/integration/controller/ModelViewController.java new file mode 100644 index 000000000..331a0fbb5 --- /dev/null +++ b/kernel-d-mongodb/mongodb-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/mongodb/integration/controller/ModelViewController.java @@ -0,0 +1,21 @@ +package cn.stylefeng.roses.kernel.mongodb.integration.controller; + +import cn.stylefeng.roses.kernel.scanner.api.annotation.ApiResource; +import cn.stylefeng.roses.kernel.scanner.api.annotation.GetResource; +import org.springframework.stereotype.Controller; + +/** + * @author huziyang + * @create 2021-03-30 15:21 + */ +@Controller +@ApiResource(name = "MongoDB文件管理界面渲染控制器") +public class ModelViewController { + + + @GetResource(name = "Mongodb文件列表视图", path = "/view/mongodb/file") + public String mongodbFile() { + return "/modular/mongodb/fileList.html"; + } + +} diff --git a/kernel-d-mongodb/mongodb-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/mongodb/integration/controller/MongoFileController.java b/kernel-d-mongodb/mongodb-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/mongodb/integration/controller/MongoFileController.java new file mode 100644 index 000000000..d25a15efa --- /dev/null +++ b/kernel-d-mongodb/mongodb-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/mongodb/integration/controller/MongoFileController.java @@ -0,0 +1,63 @@ +package cn.stylefeng.roses.kernel.mongodb.integration.controller; + +import cn.stylefeng.roses.kernel.mongodb.api.MongoFileApi; +import cn.stylefeng.roses.kernel.mongodb.file.entity.MongoFileEntity; +import cn.stylefeng.roses.kernel.rule.pojo.response.ResponseData; +import cn.stylefeng.roses.kernel.rule.pojo.response.SuccessResponseData; +import cn.stylefeng.roses.kernel.scanner.api.annotation.ApiResource; +import cn.stylefeng.roses.kernel.scanner.api.annotation.GetResource; +import cn.stylefeng.roses.kernel.scanner.api.annotation.PostResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Optional; + +/** + * @author huziyang + * @create 2021-03-31 17:28 + */ +@RestController +@ApiResource(name = "Mongodb文件接口控制器") +public class MongoFileController { + + @Resource + private MongoFileApi mongoFileApi; + + @PostResource(name = "Mongodb文件新增", path = "/view/mongodb/file/add") + public ResponseData mongodbFileAdd(@RequestPart("file") MultipartFile file) { + return new SuccessResponseData(mongoFileApi.saveFile(file)); + } + + @PostResource(name = "Mongodb文件删除", path = "/view/mongodb/file/del") + public ResponseData mongodbFileDel(@RequestParam String id) { + mongoFileApi.removeFile(id); + return new SuccessResponseData(); + } + + @GetResource(name = "Mongodb文件列表", path = "/view/mongodb/file/list") + public ResponseData mongodbFileList(MongoFileEntity mongoFileEntity) { + return new SuccessResponseData(mongoFileApi.getFilesByPage(mongoFileEntity)); + } + + @GetResource(name = "Mongodb文件下载", path = "/view/mongodb/file/down") + public ResponseEntity mongodbFileDown(@RequestParam String id) throws UnsupportedEncodingException { + Optional file = mongoFileApi.getFileById(id); + if(file.isPresent()){ + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; fileName=" + URLEncoder.encode(file.get().getName() , "utf-8")) + .header(HttpHeaders.CONTENT_TYPE, "application/octet-stream") + .body(file.get().getContent()); + }else { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("not found"); + } + } + +} diff --git a/kernel-d-mongodb/mongodb-integration-beetl/src/main/resources/assets/modular/mongodb/fileList.js b/kernel-d-mongodb/mongodb-integration-beetl/src/main/resources/assets/modular/mongodb/fileList.js new file mode 100644 index 000000000..ab7f05e78 --- /dev/null +++ b/kernel-d-mongodb/mongodb-integration-beetl/src/main/resources/assets/modular/mongodb/fileList.js @@ -0,0 +1,99 @@ +layui.use(['table', 'form', 'func', 'HttpRequest', 'util', 'upload'], function () { + + var $ = layui.$; + var table = layui.table; + var form = layui.form; + var func = layui.func; + var HttpRequest = layui.HttpRequest; + var util = layui.util; + var upload = layui.upload; + + // 模型设计管理 + var MongoFile = { + tableId: "fileList" + }; + + // 初始化表格的列 + MongoFile.initColumn = function () { + return [[ + {type: 'checkbox'}, + {field: 'id', title: '文件编号', width: 200}, + {field: 'name', title: '文件名称', width: 200}, + {field: 'uploadUserId', title: '创建人编号'}, + {field: 'uploadDate', title: '创建日期'}, + {align: 'center', toolbar: '#tableBar', title: '操作', width: 250} + ]]; + }; + + // 点击查询按钮 + MongoFile.search = function () { + var queryData = {}; + queryData['name'] = $("#fileName").val(); + table.reload(MongoFile.tableId, { + where: queryData, + page: {curr: 1} + }); + }; + + // 点击删除 + MongoFile.delete = function (data) { + var operation = function () { + var httpRequest = new HttpRequest(Feng.ctxPath + "/view/mongodb/file/del?id="+data.id, 'post', function (data) { + Feng.success("删除成功!"); + table.reload(MongoFile.tableId); + }, function (data) { + Feng.error("删除失败!" + data.message + "!"); + }); + httpRequest.set(data); + httpRequest.start(true); + }; + Feng.confirm("是否删除文件" + data.name + "?", operation); + }; + + + // 渲染表格 + var tableResult = table.render({ + elem: '#' + MongoFile.tableId, + url: Feng.ctxPath + '/view/mongodb/file/list', + page: true, + request: {pageName: 'pageNo', limitName: 'pageSize'}, + height: "full-158", + cellMinWidth: 100, + cols: MongoFile.initColumn(), + parseData: Feng.parseData + }); + + // 搜索按钮点击事件 + $('#btnSearch').click(function () { + MongoFile.search(); + }); + + + // 上传文件的点击事件 + upload.render({ + elem: '#modelUpload', + url: Feng.ctxPath + '/view/mongodb/file/add', + accept: 'file', + size: 10000, // 单位kb + done: function (res) { + Feng.success("上传文件成功!"); + MongoFile.search(); + }, + error: function (err) { + Feng.error("上传文件失败!" + err.message); + } + }); + + // 工具条点击事件 + table.on('tool(' + MongoFile.tableId + ')', function (obj) { + var data = obj.data; + var event = obj.event; + + if (event === 'down') { + window.open(Feng.ctxPath + '/view/mongodb/file/down?id=' + data.id); + } else if (event === 'delete') { + MongoFile.delete(data); + } + }); + +}); diff --git a/kernel-d-mongodb/mongodb-integration-beetl/src/main/resources/pages/modular/mongodb/fileList.html b/kernel-d-mongodb/mongodb-integration-beetl/src/main/resources/pages/modular/mongodb/fileList.html new file mode 100644 index 000000000..a8beb387a --- /dev/null +++ b/kernel-d-mongodb/mongodb-integration-beetl/src/main/resources/pages/modular/mongodb/fileList.html @@ -0,0 +1,35 @@ +@layout("/layout/_container.html",{js:["/assets/modular/mongodb/fileList.js"]}){ + +
+ Mongodb文件存储 +
+ +
+
+
+
+
+
+
+
+ +
+
+ + +
+
+
+
+
+
+
+
+
+ + + +@} diff --git a/kernel-d-mongodb/mongodb-sdk-file/pom.xml b/kernel-d-mongodb/mongodb-sdk-file/pom.xml new file mode 100644 index 000000000..040ea9c86 --- /dev/null +++ b/kernel-d-mongodb/mongodb-sdk-file/pom.xml @@ -0,0 +1,45 @@ + + + + kernel-d-mongodb + cn.stylefeng.roses + 7.0.2 + + 4.0.0 + + mongodb-sdk-file + + + 8 + 8 + + + + + + + + + cn.stylefeng.roses + auth-api + 7.0.2 + true + + + + + + cn.stylefeng.roses + mongodb-api + 7.0.2 + + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + \ No newline at end of file diff --git a/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/entity/MongoFileEntity.java b/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/entity/MongoFileEntity.java new file mode 100644 index 000000000..419f2d9e0 --- /dev/null +++ b/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/entity/MongoFileEntity.java @@ -0,0 +1,36 @@ +package cn.stylefeng.roses.kernel.mongodb.file.entity; + +import cn.stylefeng.roses.kernel.rule.pojo.request.BaseRequest; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.Date; + +/** + * @author huziyang + * @create 2021-03-26 17:23 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Document("mongo_file") +public class MongoFileEntity extends BaseRequest { + @Id + private String id; + private String name; + private Date uploadDate; + private Long uploadUserId; + private String suffix; + private String description; + private String gridfsId; + + /** + * 分页 响应字段 + */ + private byte[] content; +} diff --git a/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/mapper/MongoFileMapper.java b/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/mapper/MongoFileMapper.java new file mode 100644 index 000000000..cf97ad1cb --- /dev/null +++ b/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/mapper/MongoFileMapper.java @@ -0,0 +1,13 @@ +package cn.stylefeng.roses.kernel.mongodb.file.mapper; + +import cn.stylefeng.roses.kernel.mongodb.file.entity.MongoFileEntity; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.repository.MongoRepository; + +/** + * @author huziyang + * @create 2021-03-26 17:27 + */ +@Configuration +public interface MongoFileMapper extends MongoRepository { +} diff --git a/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/service/MongoFileService.java b/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/service/MongoFileService.java new file mode 100644 index 000000000..e9443ccf0 --- /dev/null +++ b/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/service/MongoFileService.java @@ -0,0 +1,44 @@ +package cn.stylefeng.roses.kernel.mongodb.file.service; + +import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult; +import cn.stylefeng.roses.kernel.mongodb.file.entity.MongoFileEntity; +import org.springframework.web.multipart.MultipartFile; +import java.util.Optional; + +/** + * @author huziyang + * @create 2021-03-26 17:28 + */ +public interface MongoFileService { + + /** + * 保存文件 + * @param file + * @return + */ + MongoFileEntity saveFile(MultipartFile file); + + + /** + * 删除文件 + * @param id + */ + void removeFile(String id); + + /** + * 根据id获取文件 + * @param id + * @return + */ + Optional getFileById(String id); + + + /** + * 分页获取文件 + * @param fileDocument 查询条件 + * @return + */ + PageResult getFilesByPage(MongoFileEntity fileDocument); + + +} diff --git a/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/service/impl/MongoFileServiceImpl.java b/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/service/impl/MongoFileServiceImpl.java new file mode 100644 index 000000000..1cc1d7241 --- /dev/null +++ b/kernel-d-mongodb/mongodb-sdk-file/src/main/java/cn/stylefeng/roses/kernel/mongodb/file/service/impl/MongoFileServiceImpl.java @@ -0,0 +1,114 @@ +package cn.stylefeng.roses.kernel.mongodb.file.service.impl; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.IdUtil; +import cn.stylefeng.roses.kernel.auth.api.context.LoginContext; +import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; +import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory; +import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult; +import cn.stylefeng.roses.kernel.mongodb.api.MongoFileApi; +import cn.stylefeng.roses.kernel.mongodb.file.entity.MongoFileEntity; +import cn.stylefeng.roses.kernel.mongodb.file.mapper.MongoFileMapper; +import cn.stylefeng.roses.kernel.mongodb.file.service.MongoFileService; +import com.mongodb.client.gridfs.GridFSBucket; +import com.mongodb.client.gridfs.GridFSDownloadStream; +import com.mongodb.client.gridfs.model.GridFSFile; +import lombok.extern.slf4j.Slf4j; +import org.bson.types.ObjectId; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.*; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.gridfs.GridFsResource; +import org.springframework.data.mongodb.gridfs.GridFsTemplate; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; +import java.util.Date; +import java.util.Optional; + +/** + * @author huziyang + * @create 2021-03-26 17:29 + */ +@Slf4j +@Service +public class MongoFileServiceImpl implements MongoFileService, MongoFileApi { + @Autowired + private MongoFileMapper mongoFileMapper; + @Autowired + private GridFsTemplate gridFsTemplate; + @Autowired + private GridFSBucket gridFSBucket; + + + @Override + public MongoFileEntity saveFile(MultipartFile file) { + MongoFileEntity fileDocument = new MongoFileEntity(); + fileDocument.setName(file.getOriginalFilename()); + fileDocument.setUploadDate(new Date()); + try { + // 填充登录用户的userId + LoginUser loginUser = LoginContext.me().getLoginUser(); + fileDocument.setUploadUserId(loginUser.getUserId()); + }catch (Exception e){ + // 获取不到用户登录信息,就不填充 + } + fileDocument.setSuffix(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."))); + try { + ObjectId store = gridFsTemplate.store(file.getInputStream(), IdUtil.simpleUUID(), file.getContentType()); + fileDocument.setGridfsId(String.valueOf(store)); + return mongoFileMapper.save(fileDocument); + }catch (IOException ex){ + log.error(ex.getMessage()); + } + return fileDocument; + } + + @Override + public void removeFile(String id) { + Optional fileDocumentOptional = mongoFileMapper.findById(id); + if(fileDocumentOptional.isPresent()){ + mongoFileMapper.deleteById(id); + gridFsTemplate.delete(new Query().addCriteria(Criteria.where("_id").is(fileDocumentOptional.get().getGridfsId()))); + } + } + + @Override + public Optional getFileById(String id) { + Optional fileDocumentOptional = mongoFileMapper.findById(id); + if(fileDocumentOptional.isPresent()){ + MongoFileEntity fileDocument = fileDocumentOptional.get(); + Query gridQuery = new Query().addCriteria(Criteria.where("_id").is(fileDocument.getGridfsId())); + GridFSFile fsFile = gridFsTemplate.findOne(gridQuery); + GridFSDownloadStream in = gridFSBucket.openDownloadStream(fsFile.getObjectId()); + try { + if(in.getGridFSFile().getLength() > 0){ + GridFsResource resource = new GridFsResource(fsFile, in); + fileDocument.setContent(IoUtil.readBytes(resource.getInputStream())); + return Optional.of(fileDocument); + }else { + return Optional.empty(); + } + }catch (IOException e){ + log.error(e.getMessage()); + } + } + return Optional.empty(); + } + + @Override + public PageResult getFilesByPage(MongoFileEntity fileDocument) { + Integer pageIndex = fileDocument.getPageNo(); + Integer pageSize = fileDocument.getPageSize(); + Sort sort = Sort.by(Sort.Direction.DESC, "uploadDate"); + PageRequest pageRequest = PageRequest.of(pageIndex-1, pageSize, sort); + Example example = Example.of(fileDocument, ExampleMatcher.matching() + .withIgnoreCase(true) + .withIgnorePaths("_class","pageSize","pageNo","content") + ); + Page all = mongoFileMapper.findAll(example, pageRequest); + return PageResultFactory.createPageResult(all.getContent(), mongoFileMapper.count(example), pageSize, pageIndex); + } + +} diff --git a/kernel-d-mongodb/mongodb-spring-boot-starter/pom.xml b/kernel-d-mongodb/mongodb-spring-boot-starter/pom.xml index a52e972db..8d0b006b4 100644 --- a/kernel-d-mongodb/mongodb-spring-boot-starter/pom.xml +++ b/kernel-d-mongodb/mongodb-spring-boot-starter/pom.xml @@ -17,12 +17,19 @@ - + cn.stylefeng.roses mongodb-sdk-springboot 7.0.2 + + + + cn.stylefeng.roses + mongodb-sdk-file + 7.0.2 + \ No newline at end of file diff --git a/kernel-d-mongodb/mongodb-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/mongodb/starter/GunsMongodbAutoConfiguration.java b/kernel-d-mongodb/mongodb-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/mongodb/starter/GunsMongodbAutoConfiguration.java index 1ec480d85..48613d92c 100644 --- a/kernel-d-mongodb/mongodb-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/mongodb/starter/GunsMongodbAutoConfiguration.java +++ b/kernel-d-mongodb/mongodb-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/mongodb/starter/GunsMongodbAutoConfiguration.java @@ -1,6 +1,8 @@ package cn.stylefeng.roses.kernel.mongodb.starter; +import cn.stylefeng.roses.kernel.mongodb.api.MongoFileApi; import cn.stylefeng.roses.kernel.mongodb.api.MongodbApi; +import cn.stylefeng.roses.kernel.mongodb.file.service.impl.MongoFileServiceImpl; import cn.stylefeng.roses.kernel.mongodb.service.impl.GunsMapServiceImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -13,11 +15,17 @@ import org.springframework.context.annotation.Configuration; public class GunsMongodbAutoConfiguration { + @Bean public MongodbApi mongodbApi() { return new GunsMapServiceImpl(); } + @Bean + public MongoFileApi mongoFileApi() { + return new MongoFileServiceImpl(); + } + } diff --git a/kernel-d-mongodb/pom.xml b/kernel-d-mongodb/pom.xml index ba0adf120..ce25670ed 100644 --- a/kernel-d-mongodb/pom.xml +++ b/kernel-d-mongodb/pom.xml @@ -15,6 +15,8 @@ mongodb-api mongodb-sdk-springboot mongodb-spring-boot-starter + mongodb-sdk-file + mongodb-integration-beetl