文章目录

  • 实体类
  • controller
  • service
    • 数据转换的工具类
    • file工具类

Hutool-http针对JDK的HttpUrlConnection做一层封装,简化了HTTPS请求、文件上传、Cookie记忆等操作,使Http请求变得无比简单。
用的是smms图床。
依赖:

        <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.12</version></dependency>

实体类

@Data
public class PictureDto implements Serializable {/** ID */private Long id;/** 上传日期 */private Timestamp createTime;/** 删除的URL */private String deleteUrl;/** 图片名称 */private String filename;/** 图片高度 */private String height;/** 图片大小 */private String size;/** 图片地址 */private String url;/** 用户名称 */private String username;/** 图片宽度 */private String width;/** 文件的MD5值 */private String md5code;
}

controller

@RestController
@RequestMapping("/api/pictures")
@Api(tags = "工具:免费图床管理")
public class PictureController {private final IGenerator generator;private final PictureService pictureService;public PictureController(IGenerator generator, PictureService pictureService) {this.generator = generator;this.pictureService = pictureService;}@Log("查询图片")@PreAuthorize("@el.check('pictures:list')")@GetMapping@ApiOperation("查询图片")public ResponseEntity<Object> getRoles(PictureQueryCriteria criteria, Pageable pageable) {return new ResponseEntity<>(pictureService.queryAll(criteria, pageable), HttpStatus.OK);}@Log("导出数据")@ApiOperation("导出数据")@GetMapping(value = "/download")@PreAuthorize("@el.check('pictures:list')")public void download(HttpServletResponse response, PictureQueryCriteria criteria) throws IOException {pictureService.download(generator.convert(pictureService.queryAll(criteria), PictureDto.class), response);}@Log("上传图片")@PreAuthorize("@el.check('pictures:add')")@PostMapping@ApiOperation("上传图片")public ResponseEntity<Object> upload(@RequestParam MultipartFile file) {String userName = SecurityUtils.getUsername();Picture picture = pictureService.upload(file, userName);return new ResponseEntity<>(picture, HttpStatus.OK);}@Log("同步图床数据")@ApiOperation("同步图床数据")@PostMapping(value = "/synchronize")public ResponseEntity<Object> synchronize() {pictureService.synchronize();return new ResponseEntity<>(HttpStatus.OK);}@Log("多选删除图片")@ApiOperation("多选删除图片")@PreAuthorize("@el.check('pictures:del')")@DeleteMappingpublic ResponseEntity<Object> deleteAll(@RequestBody Long[] ids) {pictureService.deleteAll(ids);return new ResponseEntity<>(HttpStatus.OK);}
}

service

package co.yixiang.tools.service.impl;import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import co.yixiang.common.service.impl.BaseServiceImpl;
import co.yixiang.common.utils.QueryHelpPlus;
import co.yixiang.dozer.service.IGenerator;
import co.yixiang.exception.BadRequestException;
import co.yixiang.tools.domain.Picture;
import co.yixiang.tools.service.PictureService;
import co.yixiang.tools.service.dto.PictureDto;
import co.yixiang.tools.service.dto.PictureQueryCriteria;
import co.yixiang.tools.service.mapper.PictureMapper;
import co.yixiang.utils.FileUtil;
import co.yixiang.utils.TranslatorUtil;
import co.yixiang.utils.ValidationUtil;
import co.yixiang.utils.YshopConstant;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;/*** @author hupeng* @date 2020-05-13*/
@Service
//@AllArgsConstructor
//@CacheConfig(cacheNames = "picture")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class PictureServiceImpl extends BaseServiceImpl<PictureMapper, Picture> implements PictureService {private final IGenerator generator;
// IGenerator是一个自定义的数据转化接口@Value("${smms.token}")private String token;//是用于图床上传文件的token
//在yml文件中配置:
//# sm.ms 图床的 token
//smms:
//  token: 1oOP3ykFDI0K6ifmtvU7c8Y1eTWZSlylprivate static final String SUCCESS = "success";private static final String CODE = "code";private static final String MSG = "message";public PictureServiceImpl(IGenerator generator) {this.generator = generator;}@Override//@Cacheablepublic Map<String, Object> queryAll(PictureQueryCriteria criteria, Pageable pageable) {getPage(pageable);PageInfo<Picture> page = new PageInfo<>(queryAll(criteria));Map<String, Object> map = new LinkedHashMap<>(2);map.put("content", generator.convert(page.getList(), PictureDto.class));map.put("totalElements", page.getTotal());return map;}@Override//@Cacheablepublic List<Picture> queryAll(PictureQueryCriteria criteria) {return baseMapper.selectList(QueryHelpPlus.getPredicate(Picture.class, criteria));}@Overridepublic void download(List<PictureDto> all, HttpServletResponse response) throws IOException {List<Map<String, Object>> list = new ArrayList<>();for (PictureDto picture : all) {Map<String, Object> map = new LinkedHashMap<>();map.put("上传日期", picture.getCreateTime());map.put("删除的URL", picture.getDeleteUrl());map.put("图片名称", picture.getFilename());map.put("图片高度", picture.getHeight());map.put("图片大小", picture.getSize());map.put("图片地址", picture.getUrl());map.put("用户名称", picture.getUsername());map.put("图片宽度", picture.getWidth());map.put("文件的MD5值", picture.getMd5code());list.add(map);}FileUtil.downloadExcel(list, response);}@Override@Transactional(rollbackFor = Throwable.class)public Picture upload(MultipartFile multipartFile, String username) {File file = FileUtil.toFile(multipartFile);// 验证是否重复上传Picture picture = this.getOne(new LambdaQueryWrapper<Picture>().eq(Picture::getMd5code, FileUtil.getMd5(file)));if (picture != null) {return picture;}HashMap<String, Object> paramMap = new HashMap<>(1);paramMap.put("smfile", file);// 上传文件String result = HttpRequest.post(YshopConstant.Url.SM_MS_URL + "/v2/upload").header("Authorization", token).form(paramMap)//设置map类型表单数据.timeout(20000).execute().body();//获取响应主体JSONObject jsonObject = JSONUtil.parseObj(result);if (!jsonObject.get(CODE).toString().equals(SUCCESS)) {throw new BadRequestException(TranslatorUtil.translate(jsonObject.get(MSG).toString()));}picture = JSON.parseObject(jsonObject.get("data").toString(), Picture.class);picture.setSize(FileUtil.getSize(Integer.parseInt(picture.getSize())));picture.setUsername(username);picture.setMd5code(FileUtil.getMd5(file));picture.setFilename(FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename()) + "." + FileUtil.getExtensionName(multipartFile.getOriginalFilename()));this.save(picture);//删除临时文件FileUtil.del(file);// FileUtil是PathUtil的子类 是cn.hutool.core.io包下return picture;}@Overridepublic Picture findById(Long id) {Picture picture = this.getById(id);ValidationUtil.isNull(picture.getId(), "Picture", "id", id);return picture;}@Overridepublic void deleteAll(Long[] ids) {for (Long id : ids) {Picture picture = findById(id);try {HttpUtil.get(picture.getDeleteUrl());this.removeById(id);} catch (Exception e) {this.removeById(id);}}}@Overridepublic void synchronize() {//链式构建请求//Hutool-http针对JDK的HttpUrlConnection做一层封装,简化了HTTPS请求、文件上传、Cookie记忆等操作,使Http请求变得无比简单String result = HttpRequest.get(YshopConstant.Url.SM_MS_URL + "/v2/upload_history")//头信息,多个头信息多次调用此方法即可.header("Authorization", token).timeout(20000).execute().body();JSONObject jsonObject = JSONUtil.parseObj(result);List<Picture> pictures = JSON.parseArray(jsonObject.get("data").toString(), Picture.class);for (Picture picture : pictures) {if (this.getOne(new LambdaQueryWrapper<Picture>().eq(Picture::getUrl, picture.getUrl())) == null) {picture.setSize(FileUtil.getSize(Integer.parseInt(picture.getSize())));picture.setUsername("System Sync");picture.setMd5code(null);this.save(picture);}}}
}

数据转换的工具类

public interface IGenerator {/*** 转换** @param s   数据对象* @param clz 复制目标类型* @return {@link T}* @Description: 单个对象的深度复制及类型转换,vo/domain , po* @author banjuer@outlook.com* @Time 2018年5月9日 下午3:53:24*/<T, S> T convert(S s, Class<T> clz);/*** 转换* @param s   数据对象* @param clz 复制目标类型* @return {@link List<T>}* @Description: list深度复制* @author banjuer@outlook.com* @Time 2018年5月9日 下午3:54:08*/<T, S> List<T> convert(List<S> s, Class<T> clz);
}
@Component
@Lazy(true)
public class EJBGenerator implements IGenerator {@Autowiredprotected Mapper dozerMapper;//Mapper 是org.dozer包下的@Overridepublic <T, S> T convert(final S s, Class<T> clz) {return s == null ? null : this.dozerMapper.map(s, clz);}@Overridepublic <T, S> List<T> convert(List<S> s, Class<T> clz) {return s == null ? null : s.stream().map(vs -> this.dozerMapper.map(vs, clz)).collect(Collectors.toList());}
}

file工具类


/*** File工具类,扩展 hutool 工具包* @author Zheng Jie* @date 2018-12-27*/
public class FileUtil extends cn.hutool.core.io.FileUtil {/*** 定义GB的计算常量*/private static final int GB = 1024 * 1024 * 1024;/*** 定义MB的计算常量*/private static final int MB = 1024 * 1024;/*** 定义KB的计算常量*/private static final int KB = 1024;/*** 格式化小数*/private static final DecimalFormat DF = new DecimalFormat("0.00");/*** MultipartFile转File*/public static File toFile(MultipartFile multipartFile) {// 获取文件名String fileName = multipartFile.getOriginalFilename();// 获取文件后缀String prefix = "." + getExtensionName(fileName);File file = null;try {// 用uuid作为文件名,防止生成的临时文件重复file = File.createTempFile(IdUtil.simpleUUID(), prefix);// MultipartFile to FilemultipartFile.transferTo(file);} catch (IOException e) {e.printStackTrace();}return file;}/*** 获取文件扩展名,不带 .*/public static String getExtensionName(String filename) {if ((filename != null) && (filename.length() > 0)) {int dot = filename.lastIndexOf('.');if ((dot > -1) && (dot < (filename.length() - 1))) {return filename.substring(dot + 1);}}return filename;}/*** Java文件操作 获取不带扩展名的文件名*/public static String getFileNameNoEx(String filename) {if ((filename != null) && (filename.length() > 0)) {int dot = filename.lastIndexOf('.');if ((dot > -1) && (dot < (filename.length()))) {return filename.substring(0, dot);}}return filename;}/*** 文件大小转换*/public static String getSize(long size) {String resultSize;if (size / GB >= 1) {//如果当前Byte的值大于等于1GBresultSize = DF.format(size / (float) GB) + "GB   ";} else if (size / MB >= 1) {//如果当前Byte的值大于等于1MBresultSize = DF.format(size / (float) MB) + "MB   ";} else if (size / KB >= 1) {//如果当前Byte的值大于等于1KBresultSize = DF.format(size / (float) KB) + "KB   ";} else {resultSize = size + "B   ";}return resultSize;}/*** 将文件名解析成文件的上传路径*/public static File upload(MultipartFile file, String filePath) {//String name = getFileNameNoEx(file.getOriginalFilename());String suffix = getExtensionName(file.getOriginalFilename());StringBuffer nowStr = fileRename();try {String fileName = nowStr + "." + suffix;String path = filePath + fileName;// getCanonicalFile 可解析正确各种路径File dest = new File(path).getCanonicalFile();// 检测是否存在目录if (!dest.getParentFile().exists()) {dest.getParentFile().mkdirs();}// 文件写入file.transferTo(dest);return dest;} catch (Exception e) {e.printStackTrace();}return null;}/*** 导出excel*/public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {String tempPath = System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx";File file = new File(tempPath);BigExcelWriter writer = ExcelUtil.getBigWriter(file);// 一次性写出内容,使用默认样式,强制输出标题writer.write(list, true);//response为HttpServletResponse对象response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");ServletOutputStream out = response.getOutputStream();// 终止后删除临时文件file.deleteOnExit();writer.flush(out, true);//此处记得关闭输出Servlet流IoUtil.close(out);}public static String getFileType(String type) {String documents = "txt doc pdf ppt pps xlsx xls docx";String music = "mp3 wav wma mpa ram ra aac aif m4a";String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";if (image.contains(type)) {return "pic";} else if (documents.contains(type)) {return "txt";} else if (music.contains(type)) {return "music";} else if (video.contains(type)) {return "vedio";} else {return "other";}}public static void checkSize(long maxSize, long size) {// 1Mint len = 1024 * 1024;if (size > (maxSize * len)) {throw new BadRequestException("文件超出规定大小");}}/*** 判断两个文件是否相同*/public static boolean check(File file1, File file2) {String img1Md5 = getMd5(file1);String img2Md5 = getMd5(file2);return img1Md5.equals(img2Md5);}/*** 判断两个文件是否相同*/public static boolean check(String file1Md5, String file2Md5) {return file1Md5.equals(file2Md5);}private static byte[] getByte(File file) {// 得到文件长度byte[] b = new byte[(int) file.length()];try {InputStream in = new FileInputStream(file);try {in.read(b);} catch (IOException e) {e.printStackTrace();}} catch (FileNotFoundException e) {e.printStackTrace();return null;}return b;}private static String getMd5(byte[] bytes) {// 16进制字符char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};try {MessageDigest mdTemp = MessageDigest.getInstance("MD5");mdTemp.update(bytes);byte[] md = mdTemp.digest();int j = md.length;char[] str = new char[j * 2];int k = 0;// 移位 输出字符串for (byte byte0 : md) {str[k++] = hexDigits[byte0 >>> 4 & 0xf];str[k++] = hexDigits[byte0 & 0xf];}return new String(str);} catch (Exception e) {e.printStackTrace();}return null;}/*** 下载文件* @param request /* @param response /* @param file /*/public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) {response.setCharacterEncoding(request.getCharacterEncoding());response.setContentType("application/octet-stream");FileInputStream fis = null;try {fis = new FileInputStream(file);response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());IOUtils.copy(fis, response.getOutputStream());response.flushBuffer();} catch (Exception e) {e.printStackTrace();} finally {if (fis != null) {try {fis.close();if (deleteOnExit) {file.deleteOnExit();}} catch (IOException e) {e.printStackTrace();}}}}public static String getMd5(File file) {return getMd5(getByte(file));}

用cn.hutool工具包进行图片上传下载示例相关推荐

  1. 微信js-sdk图片上传下载——java完整流程

    最近做的一个项目刚好用到微信js-sdk的图片上传接口,在这里做一下总结. 在这里能知道使用js api的基本配置https://mp.weixin.qq.com/wiki?t=resource/re ...

  2. html5 dzzxjbd cn,UEditor实现单张图片上传至腾讯云(对象存储服务)功能(html5

    UEditor文件上传默认只支持后端语音,因为项目是前后端分离开发,所以需要前端自行实现图片上传. 这里是直接修改的 ueditor/ueditor.all.js文件 ueditor.all.js中找 ...

  3. Android开发中使用七牛云存储进行图片上传下载

    Android开发中的图片存储本来就是比较耗时耗地的事情,而使用第三方的七牛云,便可以很好的解决这些后顾之忧,最近我也是在学习七牛的SDK,将使用过程在这记录下来,方便以后使用. 先说一下七牛云的存储 ...

  4. ssm上传文件获取路径_SSM实现图片上传下载功能

    0. 基本步骤框架搭建 实现带图片上传的注册功能 实现下载功能 1. 框架搭建 Step1 创建开发项目 创建基础MVC包结构:controller.service.mapper.pojo Step2 ...

  5. ssm框架验证码图片加载不出_基于SSM框架的文件图片上传/下载功能实现

    前一段时间很多做毕业设计的同学问:如何写图片和文件的上传下载功能,今天正好有时间,所以就做了一个案例,详细的讲解这个功能. 框架结构: 对于很多做过开发的而言,上传功能肯定都用过,而且用到的场景很多, ...

  6. Java实现七牛云文件或图片上传下载

    写在前面 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家:人工智能学习网站 文章目录 写在前面 一.准备工作 1.1.为什么选择七牛云? 1.2.七牛云注册 二.ja ...

  7. 图片上传下载-功能实现

    文件上传下载 三种方式实现文件上传功能 1. 传统form表单(基本被废弃) 向后台发送数据的三种编码格式 -form表单的enctype属性 application/x-www-form-urlen ...

  8. Retrofit2实现图片上传下载携带token校验

    1. android Retrofit2 实现图片上传携带基本数据token校验 1.1. 服务端代码: package com.denganzhi.project;import java.io.Fi ...

  9. Linux下goahead3.3.6的移植以及文件上传下载示例

    #开源库下载 下载地址 https://embedthis.com/goahead/download.html 在下载地址中可以看到说明 Source Code Repository To acces ...

最新文章

  1. 入门单片机需要购买什么东西,学哪款单片机最好?
  2. R语言ggplot2进行特定国家或者地区的地图可视化、在地图上标出所有首府城市所在地(plot the locations of the capital cities)
  3. 单电源运算放大器全波整流电路_几种二极管整流电路原理图解。
  4. DNS智能解析的另类使用 让搜索引擎更快更好的收录您的网站
  5. 【交通行业】轨迹相似性度量介绍
  6. 启明云端分享| 小明实测优化后的ESP32-S2点 3.92寸分辨率为320*320的彩屏刷新帧率
  7. 2021ICPC(澳门) - LCS Spanning Tree(广义后缀自动机)
  8. 修改网站首页批处理_几个神奇的批处理,万事不求人!
  9. 联想r630服务器开启虚拟化,整合虚拟化 联想万全R630服务器上市
  10. python高级功能_python高级篇
  11. html页面怎么引用通用的头部,html 如何引入一个公共的头部和底部
  12. (14)FPGA面试题线与逻辑
  13. HIT Software Construction Lab6引发出来对锁的问题的探究
  14. 线上python课程一般多少钱-学习Python这门课程大概需要多久?费用是多少?
  15. c语言素数环实验报告,c语言素数环问题实例讲解
  16. 基于C++的职工信息管理系统
  17. librtmp linux下 编译,LibRtmp编译并导入Android Studio
  18. revit插件有哪些常用的?介绍几个常用的revit插件操作简单
  19. doc pdf html txt mht,mht文件格式介绍
  20. Django学习记录之——csrf跨站请求伪造校验

热门文章

  1. linux中date函数的使用方法,linux date -d 的一些使用方法
  2. java word 加密_如何通过Java实现加密、解密Word文档
  3. tensorflow lstm 预测_图卷积神经网络GCN与递归结构RNN相结合的时间序列预测
  4. centos7下php设置用户和组,centos系统添加/删除用户和用户组的例子
  5. 二十三、Python队列实现多线程(下篇)
  6. 微信小程序view标签内容 文本过长,自动换行的问题
  7. 成都内推 | 腾讯游戏王者荣耀算法团队招聘算法实习生
  8. 直播预告 | 长文本知识抽取:基于语义分割的文档级三元组关系抽取
  9. 明晚直播 | 做持有专利的程序员很难吗?专家教你如何申请!
  10. SIGIR 2019 开源论文 | 基于图神经网络的协同过滤算法