1:首先在项目的pom文件中添加两个依赖
<!-- 文件上传组件 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- 图片处理类 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</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<String, Object> 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<String, Object> 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<String, Object> upload(MultipartFile file) throws ServiceException {
Map<String, Object> returnMap = new HashMap<>();
try {
if (!file.isEmpty()) {
Map<String, Object> 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:
<!DOCTYPE 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<String,Object> 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<String,Object> getData() {
return data;
}
public void setData(Map<String,Object> data) {
this.data = data;
}
public void putData(String key,Object value){
if( this. data == null ){
this.data = new HashMap<String,Object>();
}
this.data.put(key, value);
}
}