图片上传返回值分析
{
"error":0
"url":图片的保存路径
"width":图片的宽度
"height":图片的高度
}
error : 表示错误信息 0 上传成功!! 1.上传失败.
url地址 : 图片虚拟路径地址(区分真实磁盘地址)
width/height : 作为图片/宽和高必须的属性.
商品回显VO封装
结构
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ImageVO {
private Integer error;
private String url;
private Integer width;
private Integer height;
// {"error":0,"url":"图片的保存路径","width":图片的宽度,"height":图片的高度}
public static ImageVO fail(){
return new ImageVO(1,null,null,null);
}
public static ImageVO success(String url,Integer width,Integer height){
return new ImageVO(1,null,null,null);
}
}
给客户端发送的信息
注解
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
- Data - 是Lombok的注解 实现get/set方法和tostring方法
- Accessors(chain = true) - 是当前类的方法名优化
- NoArgsConstructor - 无参构造
- AllArgsConstructor - 有参构造
封装状态以及信息
private Integer error;
private String url;
private Integer width;
private Integer height;
封装 状态码,地址,高度和宽度
返回的方法
public static ImageVO fail(){
return new ImageVO(1,null,null,null);
}
错误的返回值
public static ImageVO success(String url,Integer width,Integer height){
return new ImageVO(1,null,null,null);
}
正确的返回值
controller层
@RestController
@CrossOrigin("http://localhost:8081")
@RequestMapping("/")
public class imageController {
@Autowired
private ImageService imageService;
@PostMapping("upload")
public ImageVO uploadFile(MultipartFile uploadFile){
return imageService.upload(uploadFile);
}
}
MultipartFile - 方法是专门用文件上传的方法,页面发送的文件就这么接受
编辑properties配置文件
image.localDirPath=E:/Tmooc_image
image.urlPath=localhost:8080
- 1 - 图片保存的地址
- 2 - 图片显示的链接获知域名
service业务层
结构
@Service
@PropertySource(value = "classpath:/properties/image.properties",encoding = "UTF-8")
public class FileServiceImpl implements FileService{
@Value("${image.localDirPath}")
private String localDirPath; // = "E:/Tmooc_image";
@Value("${image.urlPath}")
private String urlPath; // = "localhost:8080";
@Override
public ImageVO upload(MultipartFile uploadFile){
//1.校验文件类型 abc.jpg
String fileName = uploadFile.getOriginalFilename().toLowerCase();
//1.1 利用正则表达式校验是否满足图片格式要求
if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
return ImageVO.fail();
}
//2.校验是否为图片对象
try {
BufferedImage bufferedImage = ImageIO.read(uploadFile.getInputStream());
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
if(width==0 || height==0){
return ImageVO.fail();
}
//3.实现分目录存储
//3.1 动态生成hashcode编码 之后2位一隔 生成多级目录.目录层级太深 笛卡尔积较大 遍历不便
//3.2 可以动态以当前的时间为存储的目录结构 yyyy/MM/dd
String dateDirPath =
new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
//文件存储的目录 E:/Tmooc_image/2021/01/26/
String fileDirPath = localDirPath + dateDirPath;
File fileDir = new File(fileDirPath);
if(!fileDir.exists()){ //判断文件目录是否存在
fileDir.mkdirs(); //创建目录
}
//4.利用UUID动态生图片名称 uuid.jpg
String uuid =
UUID. randomUUID().toString().replace("-", "");
//abc.jpg
String fileType = fileName.substring(fileName.lastIndexOf("."));
String newFileName = uuid + fileType;
//5.实现文件上传
File realFile = new File(fileDirPath + newFileName);
uploadFile.transferTo(realFile);
//6.编辑图片的虚拟路径
//6.1磁盘地址: E:\JT_IMAGE\2021\01\26\1b0e435933ac42cabec53b20ffbcfe90.png
//6.2虚拟地址 http://image.jt.com\2021\01\26\1b0e435933ac42cabec53b20ffbcfe90.png
String url = urlPath + dateDirPath + newFileName;
return ImageVO.success(url,width,height);
} catch (IOException e) {
e.printStackTrace();
return ImageVO.fail();
}
}
我们文件上传在业务从通过各种测试后才实现
- 1 - 图片的后缀校验文件上传是否为图片类型? jpg|png|gif…
- 2 - 为了防止恶意程序 木马.exe.jpg
- 3 - 为了保证检索速度,需要将图片 分目录存储.
- 4 - 何防止文件重名???
1 - 校验文件上传是否为图片类型
//1.校验文件类型 abc.jpg
String fileName = uploadFile.getOriginalFilename().toLowerCase();
//1.1 利用正则表达式校验是否满足图片格式要求
if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
return ImageVO.fail();
}
uploadFile – 获取图片
getOriginalFilename() – 获取上传图片的名字
toLowerCase() – 把图片的名字都要改小写
图片的后缀不许跟我们设定的一摸一样
2 - 校验是否为图片对象
BufferedImage bufferedImage = ImageIO.read(uploadFile.getInputStream());
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
if(width==0 || height==0){
return ImageVO.fail();
}
ImageIO —— 是java自己的工具类io流的方式来获取图片
read —— 是图片ImageIO里面的获取图片路径方式
uploadFile.getInputStream() —— 动态的获取客户发来的图片
BufferedImage —— Java将一副图片加载到内存中的方法是
getWidth/getHeight —— 是获取图片的宽度和高度
图片的高度或者宽度 0 那么后面的业务不执行 (可能是病毒)
3 - 实现分目录存储
String dateDirPath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
//文件存储的目录 E:/Tmooc_image/2021/01/26/
String fileDirPath = localDirPath + dateDirPath;
File fileDir = new File(fileDirPath);
if(!fileDir.exists()){ //判断文件目录是否存在
fileDir.mkdirs(); //创建目录
}
SimpleDateFormat —— 日期的格式 (y 年 M 月 d 日)
format —— 格式化时间 (当前的时间为准)
localDirPath + dateDirPath —— 拼接了图片存储路径和时间(E:/Tmooc_image/2021/01/26)
File —— 基于图片的路径和时间创建文件夹
图片存储路径和时间拼接成新的路径,如果文件夹不存在的话创建一个,如果存在的话执行下一个业务
4 - 利用UUID动态生成图片名称
String uuid = UUID.randomUUID().toString().replace("-", "");
String Filetype = filename.substring(filename.lastIndexOf("."));
String newFileName = uuid + Filetype;
UUID —— 编码自动生成器
randomUUID —— 随机生成编码
toString —— 编码转成字符串的形式
replace —— 替换字符串里面的字符 ( - 替换 空)
substring —— 定义字符串从哪里开始
filename.lastIndexOf(".") —— 定义了从图片名字李米娜的 点 开始 (.jpg)
uuid + Filetype —— 把uuid的编码拼接图片的类型 (absadfa.jpg)
好多的图片名字是相同 为了这个我们使用UUID来编码出字符串,然后获取图片的后缀 最后拼接UUID和后缀做出新的图片名称
5 - 实现图片上传
File realFile = new File(fileDirpath + newFileName);
uploadFile.transferTo(realFile);
fileDirpath + newFileName —— 图片存储的地址和存储的图片名称
transferTo —— 客户端发来的图片进行存储
存储的目录,文件夹,图片名称都有了 我们把这些拼接并且进行存储到磁盘中
6 - 编辑图片的路径
String url = urlPath + dateDirpath + newFileName;
return ImageVO.success(url, whdth, height);
查询的域名+文件文件路径+图片名称 封装成URL给客户端响应,通过URL能看图片