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.csdn.net/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 {
}