package me.zhengjie.tools.service; import me.zhengjie.tools.domain.Picture; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.web.multipart.MultipartFile; /** * @author jie * @date 2018-12-27 */ @CacheConfig(cacheNames = "picture") public interface PictureService { /** * 上传图片 * @param file * @param username * @return */ @CacheEvict(allEntries = true) Picture upload(MultipartFile file, String username); /** * 根据ID查询 * @param id * @return */ @Cacheable(key = "#p0") Picture findById(Long id); /** * 删除图片 * @param picture */ @CacheEvict(allEntries = true) void delete(Picture picture); }
package me.zhengjie.tools.service.impl; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import me.zhengjie.common.exception.BadRequestException; import me.zhengjie.common.utils.FileUtil; import me.zhengjie.common.utils.ValidationUtil; import me.zhengjie.tools.domain.Picture; import me.zhengjie.tools.repository.PictureRepository; import me.zhengjie.tools.service.PictureService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.FileSystemResource; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.util.Arrays; import java.util.Optional; /** * @author jie * @date 2018-12-27 */ @Slf4j @Service(value = "pictureService") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class PictureServiceImpl implements PictureService { @Autowired private PictureRepository pictureRepository; public static final String SUCCESS = "success"; public static final String CODE = "code"; public static final String MSG = "msg"; @Override @Transactional(rollbackFor = Throwable.class) public Picture upload(MultipartFile multipartFile, String username) { File file = FileUtil.toFile(multipartFile); //将参数合成一个请求 RestTemplate rest = new RestTemplate(); FileSystemResource resource = new FileSystemResource(file); MultiValueMap<String, Object> param = new LinkedMultiValueMap<>(); param.add("smfile", resource); //设置头部,必须 HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(param,headers); ResponseEntity<String> responseEntity = rest.exchange("https://sm.ms/api/upload", HttpMethod.POST, httpEntity, String.class); JSONObject jsonObject = JSONUtil.parseObj(responseEntity.getBody()); Picture picture = null; if(!jsonObject.get(CODE).toString().equals(SUCCESS)){ throw new BadRequestException(jsonObject.get(MSG).toString()); } //转成实体类 picture = JSON.parseObject(jsonObject.get("data").toString(), Picture.class); picture.setSize(FileUtil.getSize(Integer.valueOf(picture.getSize()))); picture.setUsername(username); picture.setFilename(FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename())+FileUtil.getExtensionName(multipartFile.getOriginalFilename())); pictureRepository.save(picture); //删除临时文件 FileUtil.deleteFile(file); return picture; } @Override public Picture findById(Long id) { Optional<Picture> picture = pictureRepository.findById(id); ValidationUtil.isNull(picture,"Picture","id",id); return picture.get(); } @Override @Transactional(rollbackFor = Exception.class) public void delete(Picture picture) { RestTemplate rest = new RestTemplate(); try { ResponseEntity<String> str = rest.getForEntity(picture.getDelete(), String.class); if(str.getStatusCode().is2xxSuccessful()){ pictureRepository.delete(picture); } //如果删除的地址出错,直接删除数据库数据 } catch(Exception e){ pictureRepository.delete(picture); } } }
package me.zhengjie.tools.service.query; import me.zhengjie.common.utils.PageUtil; import me.zhengjie.tools.domain.Picture; import me.zhengjie.tools.repository.PictureRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import java.util.ArrayList; import java.util.List; /** * @author jie * @date 2018-12-03 */ @Service @CacheConfig(cacheNames = "picture") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class PictureQueryService { @Autowired private PictureRepository pictureRepository; /** * 分页 */ @Cacheable(keyGenerator = "keyGenerator") public Object queryAll(Picture picture, Pageable pageable){ return PageUtil.toPage(pictureRepository.findAll(new Spec(picture),pageable)); } class Spec implements Specification<Picture> { private Picture picture; public Spec(Picture picture){ this.picture = picture; } @Override public Predicate toPredicate(Root<Picture> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) { List<Predicate> list = new ArrayList<Predicate>(); if(!ObjectUtils.isEmpty(picture.getFilename())){ /** * 模糊 */ list.add(cb.like(root.get("filename").as(String.class),"%"+picture.getFilename()+"%")); } Predicate[] p = new Predicate[list.size()]; return cb.and(list.toArray(p)); } } }
package me.zhengjie.tools.config; import org.springframework.boot.web.servlet.MultipartConfigFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.servlet.MultipartConfigElement; import java.io.File; /** * @date 2018-12-28 * @author https://blog.youkuaiyun.com/llibin1024530411/article/details/79474953 */ @Configuration public class MultipartConfig { /** * 文件上传临时路径 */ @Bean MultipartConfigElement multipartConfigElement() { MultipartConfigFactory factory = new MultipartConfigFactory(); String location = System.getProperty("user.dir") + "/data/tmp"; File tmpFile = new File(location); if (!tmpFile.exists()) { tmpFile.mkdirs(); } factory.setLocation(location); return factory.createMultipartConfig(); } }
package me.zhengjie.tools.domain; import lombok.Data; import org.hibernate.annotations.CreationTimestamp; import javax.persistence.*; import java.io.Serializable; import java.sql.Timestamp; /** * sm.ms图床 * * @author jie * @date 2018-12-27 */ @Data @Entity @Table(name = "picture") public class Picture implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String filename; private String url; private String size; private String height; private String width; /** * delete URl */ @Column(name = "delete_url") private String delete; private String username; @CreationTimestamp private Timestamp createTime; @Override public String toString() { return "Picture{" + "filename='" + filename + '\'' + '}'; } }
package me.zhengjie.tools.rest; import me.zhengjie.common.aop.log.Log; import me.zhengjie.common.utils.RequestHolder; import me.zhengjie.core.utils.JwtTokenUtil; import me.zhengjie.tools.domain.Picture; import me.zhengjie.tools.service.PictureService; import me.zhengjie.tools.service.query.PictureQueryService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.HashMap; import java.util.Map; /** * @author 郑杰 * @date 2018/09/20 14:13:32 */ @RestController @RequestMapping("/api") public class PictureController { @Autowired private PictureService pictureService; @Autowired private PictureQueryService pictureQueryService; @Autowired private JwtTokenUtil jwtTokenUtil; @Log(description = "查询图片") @PreAuthorize("hasAnyRole('ADMIN','PICTURE_ALL','PICTURE_SELECT')") @GetMapping(value = "/pictures") public ResponseEntity getRoles(Picture resources, Pageable pageable){ return new ResponseEntity(pictureQueryService.queryAll(resources,pageable),HttpStatus.OK); } /** * 上传图片 * @param file * @return * @throws Exception */ @Log(description = "上传图片") @PreAuthorize("hasAnyRole('ADMIN','PICTURE_ALL','PICTURE_UPLOAD')") @PostMapping(value = "/pictures") public ResponseEntity upload(@RequestParam MultipartFile file){ String userName = jwtTokenUtil.getUserName(RequestHolder.getHttpServletRequest()); Picture picture = pictureService.upload(file,userName); Map map = new HashMap(); map.put("errno",0); map.put("id",picture.getId()); map.put("data",new String[]{picture.getUrl()}); return new ResponseEntity(map,HttpStatus.OK); } /** * 删除图片 * @param id * @return */ @Log(description = "删除图片") @PreAuthorize("hasAnyRole('ADMIN','PICTURE_ALL','PICTURE_DELETE')") @DeleteMapping(value = "/pictures/{id}") public ResponseEntity delete(@PathVariable Long id) { pictureService.delete(pictureService.findById(id)); return new ResponseEntity(HttpStatus.OK); } }
package me.zhengjie.tools.repository; import me.zhengjie.tools.domain.Picture; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; /** * @author jie * @date 2018-12-27 */ public interface PictureRepository extends JpaRepository<Picture,Long>, JpaSpecificationExecutor { }