目录
1、 文件上传
1.1、 商品文件上传
1.1.1、 编辑controller类
/**
* 业务: 实现文件上传
* url: /file/upload
* 请求类型: POST
* 参数: file
* 返回值: SysResult(imageVO)
* 高级API:MultipartFile 自动维护了缓存流/自动开关
* 文件上传步骤:
* 1.获取文件名称.
* 2.准备上传文件的目录
* 3.判断目录是否存在
* 4.封装文件全路径 目录/文件名称
* 5.实现文件上传
*/
@PostMapping("/upload")
public SysResult upload(@RequestBody MultipartFile file) throws IOException {
//1.获取文件名称 a.jpg
String fileName = file.getOriginalFilename();
//2.准备文件目录
String fileDir = "G:\\images";
//3. 判断目录是否存在
File dir = new File(fileDir);
if (!dir.exists()) {
//如果目录不存在,则创建多级目录
dir.mkdirs();
}
//4.准备文件全路径
String localPath = fileDir +"\\"+ fileName;
//5.实现文件输出
file.transferTo(new File(localPath));
System.out.println("文件上传成功!!!!");
return SysResult.success();
}
1.1.2、 编辑service
package com.jt.service;
import com.jt.mapper.FileMapper;
import com.jt.vo.ImageVO;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
@Service
@Data
public class FileServiceImpl implements FileService{
@Autowired
private FileMapper fileMapper;
private String localDir = "G:\\images";
/**
* 完成校验:
* 1.校验是否为图片
* 2.木马.exe.jpg 判断是否满足图片固有属性 高度/宽度
* 3.为了提高查询效率,要求分目录存储.
* 3.1 按照后缀名分配 jpg,png,gif 效率提升不能满足要求
* 3.2 按照日期分 yyyy/MM/dd/HH 可以
* 3.3 商品分类 出现分布不均现象.
* 3.4 根据名称hash 之后截串
* demo: hash(a)=qw|er|as|dg/a.jpg
* 弊端: hash码可能出现分布不均的现象.
* 4.防止文件重名 使用uuid代替名称
* @param file
* @return
*/
@Override
public ImageVO upload(MultipartFile file) {
//1.获取图片名称 demo: abc.jpg abc.JPG
String fileName = file.getOriginalFilename();
//bug说明: 由于windows系统不区分大小写,所以将字母全部转化为小写
fileName = fileName.toLowerCase();
//利用正则判断是否为图片.
if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
//如果不是图片,则返回null,程序终止
return null;
}
System.out.println("文件类型是图片");
//2.检查文件是否为恶意程序.
//判断文件是否有宽度和高度(width height)都有则是图片
try {
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
//read方法里是个流
//BufferedImage拿到图片类型
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
if(width == 0 || height == 0){
//说明文件不是图片.
return null;
}
System.out.println("用户上传的文件确实是图片");
//3.根据时间实现目录的创建 时间--yyyy/MM/dd
String dateDir = new SimpleDateFormat("/yyyy/MM/dd/")
.format(new Date());
// "G:/images/2021/10/15
String localDirPath = localDir + dateDir;
//创建目录
File dirFile = new File(localDirPath);
if(!dirFile.exists()){
dirFile.mkdirs();
}
//4. 使用uuid替换文件名称 唯一:系统内部唯一
String uuid = UUID.randomUUID().toString()
.replace("-","");
//截取文件的后缀 aa.bb.cc.jpg
int index = fileName.lastIndexOf(".");
//获取类型 .jpg
String fileType = fileName.substring(index);
String newFileName = uuid + fileType;
//5.实现文件上传操作 目录/文件名称
String realFilePath = localDirPath + newFileName;
file.transferTo(new File(realFilePath));
System.out.println("文件上传成功!!!");
/*
6.封装返回值
* 封装虚拟路径 在各个系统之间可以灵活切换,只保存动态变化的目录
* path = 时间/uuid.type
*/
String virtualPath = dateDir + newFileName;
String url = "https://img2.baidu.com/it/u=3043039063,2684560819&fm=26&fmt=auto";
return new ImageVO(virtualPath,url,newFileName);
} catch (IOException e) {
e.printStackTrace();
return null; //表示程序有问题
}
}
}
1.1.3、 编辑ImageVO
package com.jt.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ImageVO implements Serializable {
private String virtualPath; //虚拟地址,不包含磁盘地址
private String urlPath; //URL地址信息.
private String fileName; //文件名称
}