1:首先在项目的pom文件中添加两个依赖
<dependency>
<groupId>commons-fileuploadgroupId> <artifactId>commons-fileuploadartifactId> <version>1.3.1version> dependency> <dependency> <groupId>net.coobirdgroupId> <artifactId>thumbnailatorartifactId> <version>0.4.8version> dependency>
2:resource中添加 file-message.properties 配置文件
配置文件内容如下
#文件压缩大小(大于4兆压缩)
message.fileSize=4194304
#图片保存路径
message.upPath=D:\\MyProjectName\\UploadData\\images
#压缩比例
message.scaleRatio=0.20f
#图片类型
message.imageType=png,jpg,jpeg
3:新建 MessageProperties 类,对应 file-message.properties 配置文件
@Component
@ConfigurationProperties(prefix="message")
@PropertySource("classpath:file-message.properties") public class MessageProperties { private long fileSize; //压缩大小 private double scaleRatio; //压缩比例 private String upPath; //保存路径 private String imageType; //图片类型 public long getFileSize() { return fileSize; } public void setFileSize(long fileSize) { this.fileSize = fileSize; } public double getScaleRatio() { return scaleRatio; } public void setScaleRatio(double scaleRatio) { this.scaleRatio = scaleRatio; } public String getUpPath() { return upPath; } public void setUpPath(String upPath) { this.upPath = upPath; } public String getImageType() { return imageType; } public void setImageType(String imageType) { this.imageType = imageType; } }
@PropertySource("classpath:file-message.properties")对应第二步配置文件的名称
当然也可以不新建 file-message.properties 文件, file-message.properties 文件里的内容可以直接写在 application.properties 配置文件中,那MessageProperties 类就应该按下面这种写法:
@Component
public class MessageProperties { @Value("${fileSize}") private long fileSize; //压缩大小 @Value("${scaleRatio}") private double scaleRatio; //压缩比例 @Value("${MDDIMG_LOCATION}") private String upPath; //保存路径 @Value("${imageType}") private String imageType; //图片类型 ... }
4:service层接口
public interface FileUpAndDownService { Map uploadPicture(MultipartFile file) throws ServiceException; }
5:service层接口实现
@Service
public class FileUpAndDownServiceImpl implements FileUpAndDownService { @Autowired private MessageProperties config; //用来获取file-message.properties配置文件中的信息 @Override public Map<String, Object> uploadPicture(MultipartFile file) throws ServiceException { try { Map<String, Object> resMap = new HashMap<>(); String[] IMAGE_TYPE = config.getImageType().split(","); String path = null; boolean flag = false; for (String type : IMAGE_TYPE) { if (StringUtils.endsWithIgnoreCase(file.getOriginalFilename(), type)) { flag = true; break; } } if (flag) { resMap.put("result", IStatusMessage.SystemStatus.SUCCESS.getMessage()); String uuid = UUID.randomUUID().toString().replaceAll("-", ""); // 获得文件类型 String fileType = file.getContentType(); // 获得文件后缀名称 String imageName = fileType.substring(fileType.indexOf("/") + 1); // 原名称 String oldFileName = file.getOriginalFilename(); // 新名称 String newFileName = uuid + "." + imageName; // 年月日文件夹 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String basedir = sdf.format(new Date()); // 进行压缩(大于4M) if (file.getSize() > config.getFileSize()) { // 重新生成 String newUUID = UUID.randomUUID().toString().replaceAll("-", ""); newFileName = newUUID + "." + imageName; path = config.getUpPath() + "/" + basedir + "/" + newUUID + "." + imageName; // 如果目录不存在则创建目录 File oldFile = new File(path); if (!oldFile.exists()) { oldFile.mkdirs(); } file.transferTo(oldFile); // 压缩图片 Thumbnails.of(oldFile).scale(config.getScaleRatio()).toFile(path); // 显示路径 resMap.put("path", "/" + basedir + "/" + newUUID + "." + imageName); } else { path = config.getUpPath() + "/" + basedir + "/" + uuid + "." + imageName; // 如果目录不存在则创建目录 File uploadFile = new File(path); if (!uploadFile.exists()) { uploadFile.mkdirs(); } file.transferTo(uploadFile); // 显示路径 resMap.put("path", "/" + basedir + "/" + uuid + "." + imageName); } resMap.put("oldFileName", oldFileName); resMap.put("newFileName", newFileName); resMap.put("fileSize", file.getSize()); } else { resMap.put("result", "图片格式不正确,支持png|jpg|jpeg"); } return resMap; } catch (Exception e) { e.printStackTrace(); throw new ServiceException(e.getMessage()); } } }
6:Controller层的实现
@Controller
@RequestMapping("/upload")
public class FileUploadController { private static final Logger LOGGER = LoggerFactory.getLogger(FileUploadController.class); @Autowired private FileUpAndDownService fileUpAndDownService; @RequestMapping(value = "/setFileUpload", method = RequestMethod.POST) @ResponseBody public ResponseResult setFileUpload(@RequestParam(value = "file", required = false) MultipartFile file) { ResponseResult result = new ResponseResult(); try { Map resultMap = upload(file); if (!IStatusMessage.SystemStatus.SUCCESS.getMessage().equals(resultMap.get("result"))) { result.setCode(IStatusMessage.SystemStatus.PARAM_ERROR.getCode()); result.setMessage((String) resultMap.get("msg")); return result; } result.setData(resultMap); } catch (ServiceException e) { e.printStackTrace(); LOGGER.error(">>>>>>图片上传异常,e={}", e.getMessage()); result.setCode(IStatusMessage.SystemStatus.ERROR.getCode()); result.setMessage(IStatusMessage.FILE_UPLOAD_ERROR); } return result; } private Map upload(MultipartFile file) throws ServiceException { Map returnMap = new HashMap<>(); try { if (!file.isEmpty()) { Map picMap = fileUpAndDownService.uploadPicture(file); if (IStatusMessage.SystemStatus.SUCCESS.getMessage().equals(picMap.get("result"))) { return picMap; } else { returnMap.put("result", IStatusMessage.SystemStatus.ERROR.getMessage()); returnMap.put("msg", picMap.get("result")); } } else { LOGGER.info(">>>>>>上传图片为空文件"); returnMap.put("result", IStatusMessage.SystemStatus.ERROR.getMessage()); returnMap.put("msg", IStatusMessage.FILE_UPLOAD_NULL); } } catch (Exception e) { e.printStackTrace(); throw new ServiceException(IStatusMessage.FILE_UPLOAD_ERROR); } return returnMap; } }
7:springboot项目中还需要添加下面一段代码到Application启动类中
@SpringBootApplication
//exclude表示自动配置时不包括Multipart配置
@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
public class StartApplication { public static void main(String[] args) { ... } /** * 显示声明CommonsMultipartResolver为mutipartResolver */ @Bean(name = "multipartResolver") public MultipartResolver multipartResolver() { CommonsMultipartResolver resolver = new CommonsMultipartResolver(); //resolver.setDefaultEncoding("UTF-8"); //resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常 resolver.setResolveLazily(true); resolver.setMaxInMemorySize(40960); resolver.setMaxUploadSize(3 * 1024 * 1024);//上传文件大小 3M 3*1024*1024 return resolver; } }
顶部 @EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class}) 注解不要忘了
这两段代码不加的话,可能会造成图片上传成文件夹形式,上传失败!
8:前端HTML界面,直接使用layui
HTML:
<html xmlns:th="http://www.thymeleaf.org"> <body> <link rel="stylesheet" href="/js/layui/css/layui.css"/> <script type="text/javascript" src="/js/jquery-2.1.1.min.js">script> <script type="text/javascript" src="/js/layui/layui.js">script> <script type="text/javascript" src="/js/index.js">script> <button type="button" class="layui-btn" id="uploadBtn"> <i class="layui-icon">i>上传 button> body> html>
JS:
layui.use('upload', function () { var upload = layui.upload; //执行实例 var uploadInst = upload.render({ elem: '#uploadBtn' //绑定元素 , url: '/upload/setFileUpload' //上传接口 , multiple: true , before: function (obj) { //可设置回显 console.log(obj) } , done: function (res) { console.log(res); //上传完毕回调 if (res.code != 1000) { return layer.msg('上传失败'); } else { return layer.msg('上传成功'); } } , error: function () { //请求异常回调 } }); });
ServiceException为自定义接口异常处理:
public class ServiceException extends Exception { public ServiceException() { super(); } public ServiceException(String message){ super(message); } public ServiceException(Throwable throwable){ super(throwable); } public ServiceException(String message ,Throwable throwable){ super(message, throwable); } }
IStatusMessage为自定义响应状态信息枚举类:
public interface IStatusMessage { String getCode(); String getMessage(); enum SystemStatus implements IStatusMessage { SUCCESS("1000", "操作成功"), //请求成功 ERROR("1001", "网络异常,请稍后重试~"), FILE_UPLOAD_NULL("1002","上传图片为空文件"), ; //请求失败 private String code; private String message; SystemStatus(String code, String message) { this.code = code; this.message = message; } public String getCode() { return this.code; } public String getMessage() { return this.message; } } }
ResponseResult前端响应结果类:
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
public class ResponseResult implements Serializable { private static final long serialVersionUID = -148117940294941578L; private String code; private String message; private Object obj; private Map data; //默认为hashMap,也可为对象 public String getCode() { return code; } public ResponseResult() { this.code = IStatusMessage.SystemStatus.SUCCESS.getCode(); this.message = IStatusMessage.SystemStatus.SUCCESS.getMessage(); } public ResponseResult(IStatusMessage statusMessage){ this.code = statusMessage.getCode(); this.message = statusMessage.getMessage(); } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Object getObj() { return obj; } public void setObj(Object obj) { this.obj = obj; } public Map getData() { return data; } public void setData(Map data) { this.data = data; } public void putData(String key,Object value){ if( this. data == null ){ this.data = new HashMap(); } this.data.put(key, value); } }