xiatian 6 роки тому
батько
коміт
fe94b069e1

+ 176 - 0
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/ResourceController.java

@@ -0,0 +1,176 @@
+package cn.com.qmth.examcloud.core.basic.api.controller;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Pattern;
+
+import javax.persistence.criteria.Predicate;
+import javax.validation.constraints.NotNull;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+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 com.google.common.collect.Lists;
+
+import cn.com.qmth.examcloud.api.commons.exchange.PageInfo;
+import cn.com.qmth.examcloud.api.commons.security.bean.User;
+import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.core.basic.api.controller.bean.ResourceDomain;
+import cn.com.qmth.examcloud.core.basic.dao.ResourceRepo;
+import cn.com.qmth.examcloud.core.basic.dao.entity.ResourceEntity;
+import cn.com.qmth.examcloud.core.basic.service.ResourceService;
+import cn.com.qmth.examcloud.core.basic.service.bean.ResourceInfo;
+import cn.com.qmth.examcloud.web.support.ControllerSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@Api(tags = "资源管理")
+@Transactional
+@RestController
+@RequestMapping("${$rmp.ctr.basic}/resource")
+public class ResourceController extends ControllerSupport {
+	
+	@Value("${$upyun.site.1.domain}")
+	private String upyunFileUrl;
+	@Autowired
+	private ResourceRepo resourceRepo;
+	@Autowired
+	private ResourceService resourceService;
+	
+	@ApiOperation(value = "分页查询资源")
+	@GetMapping("page/{pageNo}/{pageSize}")
+	public PageInfo<ResourceDomain> getPage(@PathVariable Integer pageNo, @PathVariable Integer pageSize,
+			@RequestParam(required = false) String name,
+			@RequestParam(required = false) Long parentId,@RequestParam(required = true) Long rootOrgId) {
+
+		if(!isSuperAdmin()) {
+			User accessUser = getAccessUser();
+			if(!rootOrgId.equals(accessUser.getRootOrgId())) {
+				throw new StatusException("100000", "无效的请求");
+			}
+		}
+
+		Specification<ResourceEntity> specification = (root, query, cb) -> {
+			List<Predicate> predicates = new ArrayList<>();
+
+			predicates.add(cb.equal(root.get("rootOrgId"), rootOrgId));
+
+			if (StringUtils.isNotBlank(name)) {
+				predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
+			}
+			if (null == parentId||-1 == parentId) {
+				predicates.add(cb.isNull(root.get("parentId")));
+			}else {
+				predicates.add(cb.equal(root.get("parentId"), parentId));
+			}
+
+
+			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+		};
+		PageRequest pageRequest = PageRequest.of(pageNo, pageSize, new Sort(Direction.ASC,"isFile").and(new Sort(Direction.DESC,"creationTime")));
+
+		Page<ResourceEntity> page = resourceRepo.findAll(specification, pageRequest);
+		Iterator<ResourceEntity> iterator = page.iterator();
+
+		List<ResourceDomain> resourceDomainList = Lists.newArrayList();
+
+		while (iterator.hasNext()) {
+			ResourceEntity next = iterator.next();
+			ResourceDomain bean = new ResourceDomain();
+			BeanUtils.copyProperties(next, bean);
+			bean.setFileUrl(upyunFileUrl+bean.getFilePath());
+			resourceDomainList.add(bean);
+		}
+		PageInfo<ResourceDomain> ret = new PageInfo<ResourceDomain>();
+		ret.setList(resourceDomainList);
+		ret.setTotal(page.getTotalElements());
+		return ret;
+	}
+
+	@ApiOperation(value = "新增资源")
+	@PostMapping("addFile")
+	public void addResource(@RequestParam @NotNull(message = "RootOrgId不能为空!") Long rootOrgId,@RequestParam @NotNull(message = "parentId不能为空!") Long parentId,
+            @RequestPart @NotNull(message = "上传文件不能为空!") MultipartFile dataFile) {
+		if(!isSuperAdmin()) {
+			User accessUser = getAccessUser();
+			if(!rootOrgId.equals(accessUser.getRootOrgId())) {
+				throw new StatusException("100021", "无效的请求");
+			}
+		}
+		String fileName=dataFile.getOriginalFilename();
+		String regex="^[a-zA-Z\\-_0-9.]{1,50}$";
+		if(!Pattern.matches(regex, fileName)) {
+			throw new StatusException("100022", "文件名长度最大为50且只能包含字母,数字,'-','_','.'");
+		}
+		resourceService.addFile(rootOrgId,parentId,dataFile);
+	}
+	@ApiOperation(value = "删除资源")
+	@DeleteMapping("/{id}")
+	public void delResource(@PathVariable Long id) {
+		Optional<ResourceEntity>  op=resourceRepo.findById(id);
+		if(op.isPresent()) {
+			ResourceEntity e=op.get();
+			if(!isSuperAdmin()) {
+				User accessUser = getAccessUser();
+				if(!e.getRootOrgId().equals(accessUser.getRootOrgId())) {
+					throw new StatusException("100031", "无效的请求");
+				}
+			}
+			if(!e.getIsFile()&&resourceRepo.countByRootOrgIdAndParentId(e.getRootOrgId(), id)>0) {
+				throw new StatusException("100032", "请先删除该目录下的文件及目录");
+			}
+			resourceRepo.deleteById(id);
+		}else {
+			throw new StatusException("100033", "文件或目录不存在");
+			
+		}
+	}
+
+	@ApiOperation(value = "新增目录")
+	@PostMapping("addDir")
+	public void addDir(@RequestBody ResourceDomain domain) {
+		if (StringUtils.isBlank(domain.getName())) {
+			throw new StatusException("100001", "目录名称不能为空");
+		}
+		String regex="^[a-zA-Z\\-_0-9]{1,50}$";
+		if(!Pattern.matches(regex, domain.getName())) {
+			throw new StatusException("100005", "目录名称必须为1-50位字母,数字,'-','_'组合");
+		}
+		if (domain.getRootOrgId()==null) {
+			throw new StatusException("100002", "RootOrgId不能为空");
+		}
+		if (domain.getParentId()==null) {
+			throw new StatusException("100003", "ParentId不能为空");
+		}
+		if(!isSuperAdmin()) {
+			User accessUser = getAccessUser();
+			if(!domain.getRootOrgId().equals(accessUser.getRootOrgId())) {
+				throw new StatusException("100004", "无效的请求");
+			}
+		}
+		ResourceInfo info=new ResourceInfo();
+		BeanUtils.copyProperties(domain, info);
+		resourceService.addDir(info);
+	}
+
+}

+ 78 - 0
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/bean/ResourceDomain.java

@@ -0,0 +1,78 @@
+package cn.com.qmth.examcloud.core.basic.api.controller.bean;
+
+import java.util.Date;
+
+import cn.com.qmth.examcloud.api.commons.exchange.JsonSerializable;
+
+public class ResourceDomain implements JsonSerializable {
+
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -8364653908915038360L;
+	private Long id;
+	private Long rootOrgId;
+	private String name;
+	private Boolean isFile;
+	private String suffix;
+	private String filePath;
+	private String fileUrl;
+	private Long parentId;
+	private Date creationTime;
+	public Long getId() {
+		return id;
+	}
+	public void setId(Long id) {
+		this.id = id;
+	}
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public Boolean getIsFile() {
+		return isFile;
+	}
+	public void setIsFile(Boolean isFile) {
+		this.isFile = isFile;
+	}
+	public String getSuffix() {
+		return suffix;
+	}
+	public void setSuffix(String suffix) {
+		this.suffix = suffix;
+	}
+	public String getFilePath() {
+		return filePath;
+	}
+	public void setFilePath(String filePath) {
+		this.filePath = filePath;
+	}
+	public String getFileUrl() {
+		return fileUrl;
+	}
+	public void setFileUrl(String fileUrl) {
+		this.fileUrl = fileUrl;
+	}
+	public Long getParentId() {
+		return parentId;
+	}
+	public void setParentId(Long parentId) {
+		this.parentId = parentId;
+	}
+	public Date getCreationTime() {
+		return creationTime;
+	}
+	public void setCreationTime(Date creationTime) {
+		this.creationTime = creationTime;
+	}
+
+}

+ 19 - 0
examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/ResourceRepo.java

@@ -0,0 +1,19 @@
+package cn.com.qmth.examcloud.core.basic.dao;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.repository.query.QueryByExampleExecutor;
+
+import cn.com.qmth.examcloud.core.basic.dao.entity.ResourceEntity;
+
+public interface ResourceRepo
+		extends
+			JpaRepository<ResourceEntity, Long>,
+			QueryByExampleExecutor<ResourceEntity>,
+			JpaSpecificationExecutor<ResourceEntity> {
+	ResourceEntity findByRootOrgIdAndFilePath(Long rootOrgId, String filePath);
+	List<ResourceEntity> findByRootOrgIdAndParentId(Long rootOrgId, Long parentId);
+	int countByRootOrgIdAndParentId(Long rootOrgId, Long parentId);
+}

+ 79 - 0
examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/entity/ResourceEntity.java

@@ -0,0 +1,79 @@
+package cn.com.qmth.examcloud.core.basic.dao.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Index;
+import javax.persistence.Table;
+
+import cn.com.qmth.examcloud.web.jpa.JpaEntity;
+
+@Entity
+@Table(name = "EC_B_RESOURCE", indexes = {
+		@Index(name = "IDX_B_RESOURCE_000001", columnList = "rootOrgId,parentId", unique = false),
+		@Index(name = "IDX_B_RESOURCE_000002", columnList = "rootOrgId,filePath", unique = true)})
+public class ResourceEntity extends JpaEntity {
+	private static final long serialVersionUID = 4326176782077577894L;
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	private Long id;
+
+	@Column(nullable = false)
+	private Long rootOrgId;
+	@Column(nullable = false)
+	private String name;
+	@Column(nullable = false)
+	private Boolean isFile;
+	@Column(nullable = true)
+	private String suffix;
+	@Column(nullable = false)
+	private String filePath;
+	@Column(nullable = true)
+	private Long parentId;
+	public Long getId() {
+		return id;
+	}
+	public void setId(Long id) {
+		this.id = id;
+	}
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public Boolean getIsFile() {
+		return isFile;
+	}
+	public void setIsFile(Boolean isFile) {
+		this.isFile = isFile;
+	}
+	public String getSuffix() {
+		return suffix;
+	}
+	public void setSuffix(String suffix) {
+		this.suffix = suffix;
+	}
+	public String getFilePath() {
+		return filePath;
+	}
+	public void setFilePath(String filePath) {
+		this.filePath = filePath;
+	}
+	public Long getParentId() {
+		return parentId;
+	}
+	public void setParentId(Long parentId) {
+		this.parentId = parentId;
+	}
+
+}

+ 12 - 0
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/ResourceService.java

@@ -0,0 +1,12 @@
+package cn.com.qmth.examcloud.core.basic.service;
+
+import org.springframework.web.multipart.MultipartFile;
+
+import cn.com.qmth.examcloud.core.basic.service.bean.ResourceInfo;
+
+public interface ResourceService {
+
+
+	void addDir(ResourceInfo info);
+	void addFile(Long rootOrgId,Long parentId,MultipartFile dataFile);
+}

+ 77 - 0
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/bean/ResourceInfo.java

@@ -0,0 +1,77 @@
+package cn.com.qmth.examcloud.core.basic.service.bean;
+
+import java.util.Date;
+
+import cn.com.qmth.examcloud.api.commons.exchange.JsonSerializable;
+
+public class ResourceInfo implements JsonSerializable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 5355007419690855633L;
+	private Long id;
+	private Long rootOrgId;
+	private String name;
+	private Boolean isFile;
+	private String suffix;
+	private String filePath;
+	private String fileUrl;
+	private Long parentId;
+	private Date creationTime;
+	public Long getId() {
+		return id;
+	}
+	public void setId(Long id) {
+		this.id = id;
+	}
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public Boolean getIsFile() {
+		return isFile;
+	}
+	public void setIsFile(Boolean isFile) {
+		this.isFile = isFile;
+	}
+	public String getSuffix() {
+		return suffix;
+	}
+	public void setSuffix(String suffix) {
+		this.suffix = suffix;
+	}
+	public String getFilePath() {
+		return filePath;
+	}
+	public void setFilePath(String filePath) {
+		this.filePath = filePath;
+	}
+	public String getFileUrl() {
+		return fileUrl;
+	}
+	public void setFileUrl(String fileUrl) {
+		this.fileUrl = fileUrl;
+	}
+	public Long getParentId() {
+		return parentId;
+	}
+	public void setParentId(Long parentId) {
+		this.parentId = parentId;
+	}
+	public Date getCreationTime() {
+		return creationTime;
+	}
+	public void setCreationTime(Date creationTime) {
+		this.creationTime = creationTime;
+	}
+
+}

+ 106 - 0
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/ResourceServiceImpl.java

@@ -0,0 +1,106 @@
+package cn.com.qmth.examcloud.core.basic.service.impl;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.commons.fileupload.disk.DiskFileItem;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.commons.CommonsMultipartFile;
+
+import cn.com.qmth.examcloud.api.commons.exchange.FormFilePart;
+import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.core.basic.dao.ResourceRepo;
+import cn.com.qmth.examcloud.core.basic.dao.entity.ResourceEntity;
+import cn.com.qmth.examcloud.core.basic.service.ResourceService;
+import cn.com.qmth.examcloud.core.basic.service.bean.ResourceInfo;
+import cn.com.qmth.examcloud.exchange.inner.api.UpyunCloudService;
+import cn.com.qmth.examcloud.exchange.inner.api.request.PutFileReq;
+
+@Service
+public class ResourceServiceImpl implements ResourceService {
+	private static final String fileRootPath="/net_disk";
+	private static final String filePathSeparate="/";
+	@Autowired
+	ResourceRepo resourceRepo;
+	@Autowired
+	UpyunCloudService upyunCloudService;
+	@Override
+	public void addDir(ResourceInfo info) {
+		ResourceEntity e=new ResourceEntity();
+		e.setName(info.getName());
+		e.setRootOrgId(info.getRootOrgId());
+		e.setIsFile(false);
+		if(info.getParentId()==null||info.getParentId().longValue()==-1) {
+			e.setParentId(null);
+			e.setFilePath(fileRootPath+filePathSeparate+info.getRootOrgId()+filePathSeparate+info.getName());
+		}else {
+			e.setParentId(info.getParentId());
+			Optional<ResourceEntity>  op=resourceRepo.findById(info.getParentId());
+			if(op.isPresent()) {
+				ResourceEntity pe=op.get();
+				e.setFilePath(pe.getFilePath()+filePathSeparate+info.getName());
+			}else {
+				throw new StatusException("100000", "上级目录不存在");
+			}
+		}
+		try {
+			resourceRepo.save(e);
+		} catch (DataIntegrityViolationException e1) {
+			if(e1.getMessage().contains("IDX_B_RESOURCE_000002")) {
+				throw new StatusException("100001", "目录已存在");
+			}else {
+				throw e1;
+			}
+		}
+	}
+	@Override
+	public void addFile(Long rootOrgId, Long parentId, MultipartFile dataFile) {
+		ResourceEntity e=new ResourceEntity();
+		String fileName=dataFile.getOriginalFilename();
+		e.setName(fileName);
+		e.setRootOrgId(rootOrgId);
+		e.setIsFile(true);
+        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
+        e.setSuffix(suffix);
+		if(parentId==null||parentId.longValue()==-1) {
+			e.setParentId(null);
+			e.setFilePath(fileRootPath+filePathSeparate+rootOrgId+filePathSeparate+fileName);
+		}else {
+			e.setParentId(parentId);
+			Optional<ResourceEntity>  op=resourceRepo.findById(parentId);
+			if(op.isPresent()) {
+				ResourceEntity pe=op.get();
+				e.setFilePath(pe.getFilePath()+filePathSeparate+fileName);
+			}else {
+				throw new StatusException("100020", "上级目录不存在");
+			}
+		}
+		ResourceEntity olde=resourceRepo.findByRootOrgIdAndFilePath(rootOrgId, e.getFilePath());
+		if(olde!=null) {
+			olde.setUpdateTime(new Date());
+			resourceRepo.save(olde);
+		}else {
+			resourceRepo.save(e);
+		}
+		PutFileReq req=new PutFileReq();
+		List<FormFilePart> formFilePartList =new ArrayList<FormFilePart>();
+        CommonsMultipartFile cf= (CommonsMultipartFile)dataFile; 
+        DiskFileItem fi = (DiskFileItem)cf.getFileItem(); 
+
+        File f = fi.getStoreLocation();
+		FormFilePart part = new FormFilePart("file", fileName, f);
+		formFilePartList.add(part);
+
+		req.setFormFilePartList(formFilePartList);
+		req.setSiteId("netDisk");
+		String relativePath=e.getFilePath().replaceFirst(fileRootPath, "").replaceFirst(filePathSeparate, "");
+		req.setRelativePath(relativePath);
+		upyunCloudService.putFile(req);
+	}
+}