service层
package com.example.common.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.entity.SysFile;
import com.example.common.mapper.SysFileMapper;
import com.example.common.service.SysFileService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@Slf4j
@Service
@RequiredArgsConstructor
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements SysFileService {
/**
* 图片压缩率,0.5代表50%,1代表原图不压缩
*/
public static final double scale = 0.5;
public static final String SUFFIX_THUMBNAIL = "-thumbnail";
@Value("${file-path}")
private String basePath;
/**
* 以fileId重命名文件, 并获得存储路径.
* @param fileId
* @param fileName
* @return ~/tmp/fileId.***
*/
private String getPath(String fileId, String fileName) {
/*
* String类的format()方法用于创建格式化的字符串以及连接多个字符串对象.
* ①: %s: 转换符. 字符串类型.
* ②: File.separator: 文件分隔符"\"(Window), "/"(Linux)
* ③: StrUtil.addSuffixIfNot(basePath, File.separator): basePath如果不以"\"结尾, 在后面拼接上"\"
* ④: public static final String DOT = "."
* ⑤: FileUtil.extName(fileName): 获得fileName的后缀
* */
return String.format("%s%s%s%s", StrUtil.addSuffixIfNot(basePath, File.separator), fileId, StrUtil.DOT, FileUtil.extName(fileName));
}
/**
* 以fileId重命名的文件的文件路径.
* @param fileId
* @param fileName
* @return fileId.***
*/
private String getFilePath(String fileId, String fileName) {
return String.format("%s%s%s", fileId, StrUtil.DOT, FileUtil.extName(fileName));
}
/**
* 略缩图的存储路径
* @param fileId
* @param fileName
* @return
*/
private String getThumbnailPath(String fileId, String fileName) {
return String.format("%s%s%s%s", fileId, SUFFIX_THUMBNAIL, StrUtil.DOT, FileUtil.extName(fileName));
}
/**
* 文件上传
* @param file 文件
* @return
*/
@Override
@SneakyThrows
public SysFile upload(MultipartFile file) {
/*
* Content-Type: 在Http协议消息头中, 使用Content-Type来表示具体请求中的媒体类型信息.
* 图片格式类型有: image/gif; image/jpeg; image/png
* */
// 判断是否是图片
boolean isImage = StrUtil.startWith(file.getContentType(), "image");
String fileId = IdWorker.getIdStr();
/*
* file.getOriginalFilename()得到的是上传时的文件名.
* */
String path = getPath(fileId, file.getOriginalFilename());
log.info("上传文件:类型:[{}],大小:[{}],存储路径:[{}]", file.getContentType(), file.getSize(), path);
/*
* 将流的内容写入文件
* ①: file.getInputStream(): 输入流
* ②: path: 目标文件(String-->File)
* */
File fromFile = FileUtil.writeFromStream(file.getInputStream(), path);
SysFile sysFile = new SysFile(file.getOriginalFilename(), file.getContentType(), file.getSize());
sysFile.setId(fileId);
sysFile.setPath(getFilePath(fileId, file.getOriginalFilename()));
/*
* 创建略缩图
* */
if (isImage) {
try {
Thumbnails.of(fromFile)
.scale(scale)
.toFile(FileUtil.file(getPath(fileId + SUFFIX_THUMBNAIL, file.getOriginalFilename())));
sysFile.setThumbnailPath(getThumbnailPath(fileId, file.getOriginalFilename()));
} catch (IOException e) {
log.error("创建缩略图失败", e);
}
}
/*
* 把路径保存到数据库
* */
super.save(sysFile);
return sysFile;
}
}
配置文件application.yml
# 上传文件存放路径
file-path: ~/tmp/