这个个人觉得就比较简单了。
这里不适用submit是想要实现ajax异步提交,不跳转页面。所以使用button。
var uploading = false; //上传状态
//文件上传
$("#upLoadButton").click(function(){
if(uploading){
alert("文件正在上传中,请稍候...");
return false;
}
$.ajax({
url: "/fileUpload.do",
type: 'POST',
cache: false, //上传不使用缓存
data: new FormData($('#fileUploadForm')[0]), //form表单内容使用formData组装
processData: false,
contentType: false,
dataType:"json", //返回值类型
beforeSend : function(){
uploading = true;
},
success : function(data) {
alert(data.remindMsg);
uploading = false;
}
});
});
逻辑不多说了,很简单。
先设一个变量,作为上传标志,防止用户多次点击。
然后ajax就不多说了。只说一下data。我们使用formdata来进行文件的二进制上传。
这里需要配合:
form表单:
enctype="multipart/form-data"
new FormData($('#fileUploadForm')[0])
很奇怪为什么是使用jq选择器选择dom节点后还要加一个数组[0],这个找了很多资料,也没看明白为什么这么写。留个坑吧,以后填,还有如果有人知道,希望可以帮我解答一哈~
配置类:
package com.wm.springboot.conf;
import javax.servlet.MultipartConfigElement;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 文件上传配置类
* 使用multipartFile实现
* @author maybe
*/
@Configuration
public class FileUploadConfig {
@Value("${upload.file.size}")
private String fileSize;
@Bean
public MultipartConfigElement configElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize(fileSize); //文件大小限制
//factory.setLocation("d:\\wmUpload\\"); //这个配置的话,路径一定要存在,不然会报错。
return factory.createMultipartConfig();
}
}
说明:我发现一个问题,网上找资料,说在spring boot的配置文件中配置:
upload.file.size = 1024KB
#网上找的,发现4个都不生效。。。
#multipart.maxFileSize=1Kb
#multipart.maxRequestSize=1kb
#spring.http.multipart.maxFileSize=1Kb
#spring.http.multipart.maxRequestSize=1kb
即可实现控制上传文件大小。但是我试了这四个,并不可以。也没找到相关的原因...
然后我查阅资料通过上述的配置类进行配置,即可实现。
但是,这里面有一个setLocation,这个我配置了之后发现,他不会自动生成这个文件夹。如果没有,就会报错。
而且,即使我创建了也上传不到这个文件夹。干脆自己写一个吧。
package com.wm.springboot.utils;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.wm.springboot.modelUtils.GetKey;
import com.wm.springboot.modelUtils.RespResult;
import com.wm.springboot.modelUtils.RespResultEnum;
import com.wm.springboot.modelUtils.RespResultUtil;
import com.wm.springboot.sc.entity.User;
import lombok.extern.slf4j.Slf4j;
/**
* 文件上传工具类
* 支持多文件上传
* @author maybe
*/
@Slf4j
@Controller
public class FileUpload {
/**
* (多)文件上传入口
* @param files 文件数组
* @param request
* @return
*/
@PostMapping("/fileUpload")
public @ResponseBody RespResult fileUpload(@RequestParam("file")MultipartFile[] files,HttpServletRequest request) {
return upload(files,request);
}
/**
* 上传操作,支持多文件上传
* @param files 文件数组
* @param request
*/
private RespResult upload(MultipartFile[] files,HttpServletRequest request) {
log.info("IP:{},进行文件上传——开始",request.getRemoteAddr());
int count = 0; //文件数统计
for(int i=0;i) request.getServletContext().getAttribute(GetKey.configMap.toString()))
.get(GetKey.uploadpath.toString()); // 取根目录
if (null == rootPath || "".equals(rootPath)) throw new NullPointerException(RespResultEnum.ROOTPATHISNULL.getMsg());
User user = (User) request.getSession().getAttribute(GetKey.user.toString()); // 取用户名,做中间目录
if (user != null) path = rootPath + user + "\\";
else path = rootPath + "other\\";
File file2 = new File(path);
if (!file2.exists()) file2.mkdirs();
log.info("文件存储路径path:{}", path);
return path;
}
}
参数列表中的MultipartFile类:表示接收到的上传文件。使用数组形式,表示上传的是多文件。
私有方法upload的返回值RespResult
这里不多展开了。还有待优化。回来可能会单独写一篇吧。
关于getpath方法,我写了一个监听,在启动项目时,会查询config表,把一些配置,加载到系统中。这里,我把他的根目录写到了里面。这里直接从servletcontext中取相应的key即可。后期可以试着做刷新功能。从而实现很多的动态配置,修改数据库,刷新,即可。
哦,对了,这里有一个问题,因为我们的上传文件大小限制是配置在了上传的配置类中。这时候还没有进入我们的文件上传类。
这时候如果报错,提示会很不友好。这里就需要使用权与异常处理类来帮个忙了。
package com.wm.springboot.exception;
import javax.servlet.http.HttpServletRequest;
import org.apache.tomcat.util.http.fileupload.FileUploadBase.FileSizeLimitExceededException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;
import com.wm.springboot.modelUtils.BusinessException;
import com.wm.springboot.modelUtils.RespResult;
import com.wm.springboot.modelUtils.RespResultEnum;
import com.wm.springboot.modelUtils.RespResultUtil;
import lombok.extern.slf4j.Slf4j;
/**
* 全局异常处理
* @author maybe
*/
@Slf4j
@ControllerAdvice
public class GlobalDefultExceptionHandler {
@ExceptionHandler(MultipartException.class)
@ResponseBody
public RespResult FileSizeLimitExceededExceptionHandler(HttpServletRequest request,MultipartException e){
if(e.getRootCause() instanceof FileSizeLimitExceededException) {
log.info("文件大小超过限制!");
return RespResultUtil.error(RespResultEnum.FILESIZETOOMORE);
}
//未知错误
log.error("未知错误:{}",e.getMessage());
return RespResultUtil.error(RespResultEnum.UNKONW_ERROR,e);
}
//声明要捕获的异常
@ExceptionHandler(Exception.class)
@ResponseBody
public RespResult> defultExcepitonHandler(HttpServletRequest request,Exception e) {
e.printStackTrace();
if(e instanceof BusinessException) {
log.error("业务异常:{}",e.getMessage());
BusinessException businessException = (BusinessException)e;
return RespResultUtil.error(businessException);
}else {
//未知错误
log.error("未知错误:{}",e.getMessage());
return RespResultUtil.error(RespResultEnum.UNKONW_ERROR,e);
}
}
}
嗯,这下应该就完活了。
哦,下次找机会填坑logback。现在我已经把系统内的日志替换了logback,新的日志框架。填之前的坑。