1.接口文件
2.Controller层
@RestController
@CrossOrigin
@RequestMapping("/file")
public class FileController {
@Autowired
private FileService fileService;
/**
* 业务说明: 实现图片上传
* URL: http://localhost:8091/file/upload
* 类型: post
* 参数: MultipartFile file 字节信息
* 返回值: SysResult.success()
* 问题思考:
* 1.完成图片类型校验 jpg|png|gif....
* 2.防止恶意程序 a.exe.jpg
* 3.将图片分目录存储
* 3.1.按照类型分 理论可以但是得多分配几个
* 3.2.按照时间划分. yyyy/MM/dd
* 4.自定义文件名称. 利用UUID充当图片名称.
*/
@PostMapping("/upload")
public SysResult upload(MultipartFile file) throws IOException {
ImageVO imageVO = fileService.upload(file);
if(imageVO == null){
return SysResult.fail();
}
return SysResult.success(imageVO);
}
/**
* 业务说明: 实现图片上传
* URL: http://localhost:8091/file/upload
* 类型: post
* 参数: file 字节信息
* 返回值: SysResult.success()
* 扩展:
* 一般情况下:
* 一般前端向后端服务器发送字节信息.由外到内实现数据传输.
* 采用输入流信息. InputStream file
* 使用字节流的弊端: 1.必须手动关闭, 2.代码操作繁琐
* 底层代码的实现.
* SpringMVC高级API MultipartFile 专门处理IO流操作
* 文件上传步骤:
* 1.获取文件名称
* 2.准备文件上传的目录
* 3.判断目录是否存在 存在目录: 实现上传 没有目录:创建目录
* 4.利用工具API方法,实现文件上传.
* 注意事项: MultipartFile 默认支持1M的数据
*/
/*@PostMapping("/upload")
public SysResult upload(MultipartFile file) throws IOException {
//1.获取文件名称
String fileName = file.getOriginalFilename();
//2.准备磁盘地址
String dirPath = "E:/project3/images/";
//3.将这个文件目录 封装为File对象
File dirFile = new File(dirPath);
//4.判断对象是否存在
if(!dirFile.exists()){
//如果文件目录不存在,则创建目录
dirFile.mkdirs(); //表示多级目录上传.
}
//5.封装文件全路径 E:xxx/xxx/a.jpg
String path = dirPath + fileName;
File allFile = new File(path);
//6.实现文件上传 将IO流按照指定的对象格式进行输出.
file.transferTo(allFile);
return SysResult.success();
}*/
}
3.service层
@Service
public class FileServiceImpl implements FileService{
private String localDirPath = "E:/project3/images";
private String preUrl = "http://image.jt.com";
//1.校验图片类型 xxx.jpg 校验后缀是否为jpg
@Override
public ImageVO upload(MultipartFile file) {
//1.1 获取文件名称 abc.jpg
String fileName = file.getOriginalFilename();
//1.2 全部转化为小写字母
fileName = fileName.toLowerCase();
//1.3正则校验是否为图片类型
if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
//图片类型 不匹配 程序应该终止
return null;
}
//2.校验是否为恶意程序 怎么判断就是一张图 高度和宽度
//2.1 通过图片对象进行处理
try {
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
int height = bufferedImage.getHeight();
int width = bufferedImage.getWidth();
if(height == 0 || width == 0){
return null;
}
//3.将图片分目录存储 yyyy/MM/dd
String dateDir = new SimpleDateFormat("/yyyy/MM/dd/")
.format(new Date());
String dateDirPath = localDirPath + dateDir;
File dirFile = new File(dateDirPath);
if(!dirFile.exists()){
dirFile.mkdirs();
}
//4.防止文件重名 动态生成UUID.类型
//4.1 动态生成UUID
String uuid = UUID.randomUUID().toString()
.replace("-","");
//4.2 获取图片类型 abc.jpg .jpg
String fileType = fileName.substring(fileName.lastIndexOf("."));
// uuid.jpg
String newFileName = uuid + fileType;
//5.实现文件上传 1.准备全文件路径 2. 封装对象实现上传
String path = dateDirPath + newFileName;
file.transferTo(new File(path));
//6. 实现ImageVO数据的返回
//6.1 准备虚拟路径 /2021/11/11/uuid.jpg
String virtualPath = dateDir + newFileName;
//6.2 准备URL地址 域名前缀 + 虚拟路径
String url = preUrl + virtualPath;
System.out.println(url);
return new ImageVO(virtualPath,url,newFileName);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
4.ImageVo文件
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ImageVO {
private String virtualPath; //图片的虚拟路径
private String urlPath; //图片的虚拟路径
private String fileName; //文件上传后的文件名字;
}