4 文件上传
4.1文件上传入门案例
4.1.1 编辑HTML页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>实现文件长传</h1>
<!--enctype="开启多媒体标签" -->
<form action="http://localhost:8091/file" method="post"
enctype="multipart/form-data">
<input name="fileImage" type="file" />
<input type="submit" value="提交"/>
</form>
</body>
</html>
4.1.2 编辑FileController
package com.jt.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@RestController
public class FileController {
/**
* 完成文件上传的入门案例
* url地址: http://localhost:8091/file
* 请求参数: fileImage
* 返回值: 文件上传成功
*
* 利用SpringMVC中提供的工具API,实现文件上传的简化.
* 记住类型:MultipartFile
* 实现步骤:
* 1.接收资源文件
* 2.准备文件上传目录
* 3.准备文件上传的全路径 目录/文件名称
*/
@RequestMapping("/file")
public String file(MultipartFile fileImage){
//2.文件文件上传的目录
String fileDirPath = "D:/JT-SOFT/images";
File dirFile = new File(fileDirPath);
//判断文件目录是否存在
if(!dirFile.exists()){
//如果文化间目录没有,则应该新建目录
dirFile.mkdirs(); //创建多级目录
}
//3.准备文件上传的全路径. 路径+文件名称
String fileName = fileImage.getOriginalFilename(); //文件名称.后缀 123.jgp
File realFile = new File(fileDirPath+"/"+fileName);
//将字节信息输出到文件中.
try {
fileImage.transferTo(realFile); //实现文件上传
return "文件上传成功!!!";
} catch (IOException e) {
e.printStackTrace();
return "文件上传失败!!!";
}
}
}
4.2商品文件上传实现
4.2.1 富文本编辑器返回值说明
{“error”:0,“url”:“图片的保存路径”,“width”:图片的宽度,“height”:图片的高度}
属性1: error 如果在文件上传的过程中出现问题 则标识为1 ,如果没有错误 标识为0.
属性2: url 代表图片的虚拟访问地址. 磁盘地址
属性3: width/height 获取图片的宽高 可以省略.
4.2.2 封装文件上传的返回值VO
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 Integer error; //确认是否有错误 0正常 1错误
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){
return new ImageVO(0, url, null, null);
}
public static ImageVO success(String url,Integer width,Integer height){
return new ImageVO(0, url, width, height);
}
}
4.2.4 文件上传的参数说明
文件上传JS属性配置:
4.2.3 编辑FileController
说明: 文件上传时,需要注意富文本编辑器中传递的url参数.
/**
* 实现图片上传操作.
* url地址:http://localhost:8091/pic/upload?dir=image
* 参数信息: uploadFile
* 返回值: ImageVO对象
*/
@RequestMapping("/pic/upload")
public ImageVO upload(MultipartFile uploadFile){
return fileService.upload(uploadFile);
}
4.2.3编辑FileService
package com.jt.service;
import com.jt.vo.ImageVO;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@Service
public class FileServiceImpl implements FileService{
//定义图片的类型集合.
private static Set<String> imageTypeSet = new HashSet<>();
private String localDirPath = "D:/JT-SOFT/images"; //定义本地磁盘目录
static {
imageTypeSet.add(".jpg"); //字母小写类型
imageTypeSet.add(".png");
imageTypeSet.add(".gif");
//其他的省略.....
}
/**
* 1.校验文件有效性 .jpg|.png|.gif.......
* 2.校验文件是否为恶意程序 (木马.exe).jpg
* 3.提高用户检索图片的效率 分目录存储.
* 4.为了防止重名图片的提交 自定义文件名称.
* 5.实现图片的物理上传 本地磁盘中.
* 6.准备一个访问图片的虚拟路径
* * @param uploadFile
* @return
*/
@Override
public ImageVO upload(MultipartFile uploadFile) {
//1.校验图片类型 1.利用正则表达式进行校验 2.利用集合进行校验 Set 数据是否存在即可.
//1.1 获取图片名称 abc.jpg ABC.JPG
String fileName = uploadFile.getOriginalFilename();
fileName = fileName.toLowerCase(); //将所有的字母都小写
//1.2 获取图片的类型
int index = fileName.lastIndexOf(".");
String fileType = fileName.substring(index); //.jpg
if(!imageTypeSet.contains(fileType)){ //如果类型不匹配
return ImageVO.fail(); //图片上传失败.
}
//2.如何判断文件是否为恶意程序? 文件是否有图片的特有属性!!!!
//2.1将上传的文件类型利用图片的API进行转化 如果转化不成功则一定不是图片.
try {
BufferedImage bufferedImage = ImageIO.read(uploadFile.getInputStream());
//2.2校验是否有图片的特有属性 高度/宽度
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
//2.3校验宽度和高度是否有值.
if(width == 0 || height == 0){
return ImageVO.fail();
}
} catch (IOException e) {
e.printStackTrace();
return ImageVO.fail(); //返回失败即可
}
//3.实现分目录存储
// 方案1: 利用hash之后每隔2-3位截取之后拼接
// 方案2: 以时间为单位进行分隔 /yyyy/MM/dd/
//3.1 利用工具API将时间转化为指定的格式
String datePath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
//3.2 动态生成文件目录 2部分=根目录+时间目录
String localDir = localDirPath + datePath;
//3.3判断目录是否存在, 如果不存在则新建目录
File dirFile = new File(localDir);
if(!dirFile.exists()){
dirFile.mkdirs(); //如果不存在,则新建目录
}
//4. 防止文件重名,需要自定义文件名称 UUID
//4.1生成uuid
String uuid =
UUID.randomUUID().toString().replace("-", "");
//4.2动态生成文件名称 uuid +.jpg
String uuidFileName = uuid + fileType;
//5.实现文件上传 准备文件全路径 目录+文件名称
String realFilePath = localDir + uuidFileName;
//5.1封装文件真实对象
File imageFile = new File(realFilePath);
//5.2实现文件上传
try {
uploadFile.transferTo(imageFile);
} catch (IOException e) {
e.printStackTrace();
return ImageVO.fail(); //告知文件上传失败
}
//6.暂时使用京东图片代替.
// 检查文件上传业务调用是否正确
String url = "https://img14.360buyimg.com/n1/s546x546_jfs/t1/122216/5/8769/316276/5f2a160eE30a3fbfd/f742fb30fdea6239.jpg";
return ImageVO.success(url);
}
}